Microsoft MVP성태의 닷넷 이야기
.NET Framework: 778. (Unity가 사용하는) 모노 런타임의 __makeref 오류 [링크 복사], [링크+제목 복사],
조회: 20497
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 
(연관된 글이 3개 있습니다.)

(Unity가 사용하는) 모노 런타임의 __makeref 오류

아래의 글에 달린 덧글 덕분에,

C#에서 enum을 boxing 없이 int로 변환하기 - 두 번째 이야기
; https://www.sysnet.pe.kr/2/0/11506

실로 오랜만에 Mono 런타임을 설치해봤습니다. ^^

The latest Stable Mono
; https://www.mono-project.com/download/stable/

설치하고 나면 시작 메뉴에 "Open Mono x64 Command Prompt" 항목이 생깁니다. 그 명령행 창을 열고 다음의 소스 코드를,

using System;

namespace ConsoleApp1
{
    class Program
    {
        enum EnumState
        {
            A,
            B,
        }

        static void Main(string[] args)
        {
            unsafe
            {
                EnumState a = EnumState.A;
                EnumState b = EnumState.B;

                TypedReference refA = __makeref(a);
                TypedReference refB = __makeref(b);

                int* valuePtrA = (int*)*((IntPtr*)&refA);
                int* valuePtrB = (int*)*((IntPtr*)&refB);

                int expectedA = *valuePtrA;
                int expectedB = *valuePtrB;

                Console.WriteLine(expectedA);
                Console.WriteLine(expectedB);
                Console.WriteLine(expectedA == expectedB);
            }

            Console.ReadLine();
        }
    }
}

이렇게 빌드할 수 있습니다.

C:\temp>dmcs Program.cs /unsafe

실행해 보면, 결과가 잘 나옵니다.

C:\temp>Program.exe
0
1
False

오호~~~ 그런데 원하는 환경이 아닙니다. 저렇게 실행하면 ^^ 현재 윈도우에 설치된 .NET Full Framework가 올라오게 됩니다. 따라서 모노 런타임 위에서 실행하려면 다음과 같이 mono.exe를 이용해 실행해야 합니다.

c:\temp>mono Program.exe
898445256
898445256
True

출력된 898445256 값은 실행 시마다 달라지는 것으로 봐서 메모리 상의 쓰레기 값이 출력되는 듯합니다. 결과적으로, 모노 런타임은 __makeref 예약어에 대한 처리를 제대로 하지 못하는 것입니다.




그래도, Unity의 경우 AOT(Ahead of time) 컴파일러를 사용해 미리 빌드해 놓기 때문에 혹시 거기서는 정상적으로 처리하고 있지 않을까요? ^^ AOT 실행 테스트를 하려면 clang이 필요합니다. 이를 위해 LLVM을 설치해도 되지만,

LLVM Download Page 
; https://releases.llvm.org/download.html

Pre-Built Binaries:
Clang for Windows (64-bit) (.sig)
; http://releases.llvm.org/6.0.0/LLVM-6.0.0-win64.exe

어차피 clang.exe도 빌드할 때는 Visual C++의 cl.exe의 도움을 얻어야 하므로 Visual Studio를 설치해야 합니다.

Setting up Clang on Windows
; https://github.com/boostorg/hana/wiki/Setting-up-Clang-on-Windows

따라서, 그냥 Clang/LLVM을 설치하지 말고 Visual Studio에 포함된 clang 구성으로 옵션을 추가해 설치하면 됩니다. 가령 Visual Studio 2015의 경우 다음과 같은 옵션만 있으면 됩니다.

Visual Studio Professional 2015 with Update 3

Programming Languages
    - Visual C++
        - Common Tools for Visual C++ 2015
        - Microsoft Foundation Classes for C++
        - Windows XP Support for C++

Cross Platform Mobile Development
    - Visual C++ Mobile Development
        - Clang with Microsoft CodeGen (July 2016)

설치 후, 환경 변수에 PATH를 clang.exe와 link.exe에 대해 각각 다음과 같이 잡아줍니다.

[clang.exe의 위치를 PATH에 추가]
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\ClangC2\bin\amd64

[link.exe의 위치를 PATH에 추가]
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64

이후, Program.exe 바이너리를 AOT 빌드해 줘야 합니다.

mono --aot=full Program.exe

그런 다음 아래와 같이 실행할 수 있는데, 아쉽게도 오류가 발생합니다.

C:\temp>mono --full-aot Program.exe
Failed to load AOT module 'C:\Program Files\Mono\lib\mono\4.5\mscorlib.dll.dll' in aot-only mode.

왜냐하면, Program.exe가 의존하는 모듈들도 전부 AOT 상태로 빌드가 되어있어야 하기 때문입니다. 이를 위해 다음의 경로에 있는 DLL들을 전부,

C:\Program Files\Mono\lib\mono\4.5\mscorlib.dll
C:\Program Files\Mono\lib\mono\gac\I18N\4.0.0.0__0738eb9f132ed756\I18N.dll
C:\Program Files\Mono\lib\mono\gac\I18N.West\4.0.0.0__0738eb9f132ed756\I18N.West.dll

개별 폴더에 들어가 각각 다음의 명령어로 빌드해 둡니다.

mono --aot=full mscorlib.dll
mono --aot=full I18N.dll
mono --aot=full i18n.west.dll

이후 다시 실행하면 다음과 같이 결과를 볼 수 있습니다. ^^

c:\temp>mono --full-aot Program.exe
-402205784
-402205784
True

뭐... 어쩔 수 없군요. ^^ Mono 런타임은, AOT 빌드한 결과물에서도 역시 __makeref 처리를 하지 못합니다.




Mono가 저렇다는 것은, 그에 기반을 둔 현재의 Unity가 게임 빌드 결과물에서 __makeref 처리를 못한다는 것을 의미합니다. 아마도 가장 좋은 것은 .NET Core로 Unity가 이전하는 것일 텐데 가장 최근의 결과물인 2018 버전의,

Updated scripting runtime in Unity 2018.1: What does the future hold?
; https://blogs.unity3d.com/kr/2018/03/28/updated-scripting-runtime-in-unity-2018-1-what-does-the-future-hold/

질문 답변을 봐도 희망이 안 보이는 것 같습니다. ^^

Q: Is .net core on the radar for the future at all? A: It is not something we’re looking at for the near future, for a few reasons. First, it does not have a full embedding API, as Mono does. Second, it does not support enough platforms currently. We have done some experiments with it though, so I can’t rule it out entirely. But we’re focused on other priorities at the moment, like build size, iteration time improvement, GC, and C#7.





참고로, clang.exe가 설치되지 않았거나 link.exe와 함께 PATH가 정상적으로 잡혀 있지 않으면 다음과 같은 식의 컴파일 오류가 발생합니다.

C:\temp>mono --aot Program.exe
Mono Ahead of Time compiler - compiling assembly C:\temp\Program.exe
AOTID B742BABC-9819-CB33-8E48-FF192EC74425
Code: 276(29%) Info: 6(0%) Ex Info: 47(4%) Unwind Info: 41(4%) Class Info: 129(13%) PLT: 30(3%) GOT Info: 301(31%) Offsets: 121(12%) GOT: 240
Compiled: 2/2 (100%), No GOT slots: 1 (50%), Direct calls: 0 (100%)
Executing the native assembler: "clang.exe" -c -x assembler  -o C:\Users\testuser\AppData\Local\Temp\mono_aot_a03412.obj C:\Users\testuser\AppData\Local\Temp\mono_aot_a03412
'"clang.exe"' is not recognized as an internal or external command,
operable program or batch file.
AOT of image Program.exe failed.




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 6/27/2018]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




... 151  [152]  153  154  155  156  157  158  159  160  161  162  163  164  165  ...
NoWriterDateCnt.TitleFile(s)
1252정성태3/1/201225345Windows: 55. 윈도우 8 베타 설치 과정 [1]
1251정성태2/27/201229295VC++: 60. C/C++ Native 스레드 콜 스택 덤프를 얻는 공개 라이브러리 [2]파일 다운로드1
1250정성태2/27/201231408VC++: 59. C/C++ 프로젝트 빌드 속도 개선 - UnityBuild를 아세요? [3]
1249정성태2/26/201231092.NET Framework: 311. .NET 스레드 콜 스택 덤프 (5) - ICorDebug 인터페이스 사용법 [2]파일 다운로드3
1248정성태2/25/201242588.NET Framework: 310. C#의 Shift 비트 연산 정리파일 다운로드1
1247정성태2/25/201225282.NET Framework: 309. .NET 응용 프로그램에 기본 생성되는 스레드들에 대한 탐구 [1]파일 다운로드1
1246정성태2/25/201224852개발 환경 구성: 145. 한영 변환은 되지만, 정작 한글 입력이 안되는 경우
1245정성태2/25/201235570개발 환경 구성: 144. 윈도우에서도 유닉스처럼 명령행으로 원격 접속하는 방법
1244정성태2/24/201232767.NET Framework: 308. .NET System.Threading.Thread 개체에서 Native Thread Id를 구할 수 있을까? [1]파일 다운로드1
1243정성태2/23/201232715개발 환경 구성: 143. Visual Studio 2010 - .NET Framework 소스 코드 디버깅 - 두 번째 이야기 [1]
1242정성태2/20/201239578VC++: 58. API Hooking - 64비트를 고려해야 한다면? EasyHook! [7]파일 다운로드1
1241정성태2/20/201226393.NET Framework: 307. .NET 4.0 응용 프로그램을 위한 ILMerge
1240정성태2/19/201232680디버깅 기술: 48. C/C++ JNI DLL을 Visual Studio로 디버깅하는 방법 [2]
1239정성태2/19/201224295.NET Framework: 306. 컴퓨터에 실행된 프로세스 중에 닷넷 응용 프로그램임을 알 수 있는 방법 - C# [1]파일 다운로드1
1238정성태2/19/201228167.NET Framework: 305. GetPrivateProfileSection / WritePrivateProfileSection의 C# 버전파일 다운로드1
1237정성태2/18/201232498개발 환경 구성: 142. Windows Embedded POSReady 7 설치 [1]
1236정성태2/17/201228315개발 환경 구성: 141. Windows 2008 R2 RDP 라이선스 서버 설치하는 방법
1235정성태2/16/201226760.NET Framework: 304. Hyper-V의 가상 머신을 C#으로 제어하는 방법 [1]파일 다운로드1
1234정성태2/16/201227161.NET Framework: 303. 원본 파일의 공백/라인을 유지한 체 XML 파일을 저장하는 방법 [1]파일 다운로드1
1233정성태2/16/201233275.NET Framework: 302. supportedRuntime 옵션과 System.BadImageFormatException 예외 [5]
1232정성태2/9/201229193VC++: 57. 웹 브라우저에서 Flash만 빼고 다른 ActiveX를 차단할 수 있을까? [3]파일 다운로드1
1231정성태2/8/201238717VC++: 56. Win32 API 후킹 - Trampoline API Hooking [5]파일 다운로드1
1230정성태2/6/201224067개발 환경 구성: 140. 프로젝트 생성 시부터 "Enable the Visual Studio hosting process" 옵션을 끄는 방법
1229정성태2/4/201229084.NET Framework: 301. P/Invoke의 성능을 높이기 위해 C++/CLI가 선택되려면? [5]파일 다운로드1
1228정성태2/4/201278377.NET Framework: 300. C#으로 만드는 음성인식/TTS 프로그램 [47]파일 다운로드1
1227정성태2/3/201229266.NET Framework: 299. 해당 어셈블리가 Debug 빌드인지, Release 빌드인지 알아내는 방법파일 다운로드1
... 151  [152]  153  154  155  156  157  158  159  160  161  162  163  164  165  ...