성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] Working with Rust Libraries from C#...
[정성태] Detecting blocking calls using asyn...
[정성태] 아쉽게도, 커뮤니티는 아니고 개인 블로그입니다. ^^
[정성태] 질문이 잘 이해가 안 됩니다. 우선, 해당 소스코드에서 ILis...
[양승조
] var대신 dinamic으로 선언해서 해결은 했습니다. 맞는 해...
[양승조
] 또 막혔습니다. ㅠㅠ var list = props[i].Ge...
[양승조
] 아. 감사합니다. 어제는 안됐던것 같은데....정신을 차려야겠네...
[정성태] "props[i].GetValue(props[i])" 코드에서 ...
[정성태] 저렇게 조각 코드 말고, 실제로 재현이 되는 예제 프로젝트를 압...
[정성태] Modules 창(Ctrl+Shift+U)을 띄워서, 해당 Op...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>(Unity가 사용하는) 모노 런타임의 __makeref 오류</h1> <p> 아래의 글에 달린 덧글 덕분에,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C#에서 enum을 boxing 없이 int로 변환하기 - 두 번째 이야기 ; <a target='tab' href='http://www.sysnet.pe.kr/2/0/11506'>http://www.sysnet.pe.kr/2/0/11506</a> </pre> <br /> 실로 오랜만에 Mono 런타임을 설치해봤습니다. ^^<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > The latest Stable Mono ; <a target='tab' href='https://www.mono-project.com/download/stable/'>https://www.mono-project.com/download/stable/</a> </pre> <br /> 설치하고 나면 시작 메뉴에 "Open Mono x64 Command Prompt" 항목이 생깁니다. 그 명령행 창을 열고 다음의 소스 코드를,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 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; <span style='color: blue; font-weight: bold'>Console.WriteLine(expectedA); Console.WriteLine(expectedB); Console.WriteLine(expectedA == expectedB);</span> } Console.ReadLine(); } } } </pre> <br /> 이렇게 빌드할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C:\temp><span style='color: blue; font-weight: bold'>dmcs Program.cs /unsafe</span> </pre> <br /> 실행해 보면, 결과가 잘 나옵니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C:\temp>Program.exe 0 1 False </pre> <br /> 오호~~~ 그런데 원하는 환경이 아닙니다. 저렇게 실행하면 ^^ 현재 윈도우에 설치된 .NET Full Framework가 올라오게 됩니다. 따라서 모노 런타임 위에서 실행하려면 다음과 같이 mono.exe를 이용해 실행해야 합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > c:\temp><span style='color: blue; font-weight: bold'>mono</span> Program.exe 898445256 898445256 True </pre> <br /> 출력된 898445256 값은 실행 시마다 달라지는 것으로 봐서 메모리 상의 쓰레기 값이 출력되는 듯합니다. 결과적으로, 모노 런타임은 __makeref 예약어에 대한 처리를 제대로 하지 못하는 것입니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 그래도, Unity의 경우 AOT(Ahead of time) 컴파일러를 사용해 미리 빌드해 놓기 때문에 혹시 거기서는 정상적으로 처리하고 있지 않을까요? ^^ AOT 실행 테스트를 하려면 clang이 필요합니다. 이를 위해 LLVM을 설치해도 되지만,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > LLVM Download Page ; <a target='tab' href='https://releases.llvm.org/download.html'>https://releases.llvm.org/download.html</a> Pre-Built Binaries: Clang for Windows (64-bit) (.sig) ; <a target='tab' href='http://releases.llvm.org/6.0.0/LLVM-6.0.0-win64.exe'>http://releases.llvm.org/6.0.0/LLVM-6.0.0-win64.exe</a> </pre> <br /> 어차피 clang.exe도 빌드할 때는 Visual C++의 cl.exe의 도움을 얻어야 하므로 Visual Studio를 설치해야 합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Setting up Clang on Windows ; <a target='tab' href='https://github.com/boostorg/hana/wiki/Setting-up-Clang-on-Windows'>https://github.com/boostorg/hana/wiki/Setting-up-Clang-on-Windows</a> </pre> <br /> 따라서, 그냥 Clang/LLVM을 설치하지 말고 Visual Studio에 포함된 clang 구성으로 옵션을 추가해 설치하면 됩니다. 가령 Visual Studio 2015의 경우 다음과 같은 옵션만 있으면 됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 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 - <span style='color: blue; font-weight: bold'>Clang with Microsoft CodeGen (July 2016)</span> </pre> <br /> 설치 후, 환경 변수에 PATH를 clang.exe와 link.exe에 대해 각각 다음과 같이 잡아줍니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > [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 </pre> <br /> 이후, Program.exe 바이너리를 AOT 빌드해 줘야 합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > mono --aot=full Program.exe </pre> <br /> 그런 다음 아래와 같이 실행할 수 있는데, 아쉽게도 오류가 발생합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C:\temp><span style='color: blue; font-weight: bold'>mono --full-aot</span> Program.exe Failed to load AOT module 'C:\Program Files\Mono\lib\mono\4.5\mscorlib.dll.dll' in aot-only mode. </pre> <br /> 왜냐하면, Program.exe가 의존하는 모듈들도 전부 AOT 상태로 빌드가 되어있어야 하기 때문입니다. 이를 위해 다음의 경로에 있는 DLL들을 전부,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 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 </pre> <br /> 개별 폴더에 들어가 각각 다음의 명령어로 빌드해 둡니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > mono --aot=full mscorlib.dll mono --aot=full I18N.dll mono --aot=full i18n.west.dll </pre> <br /> 이후 다시 실행하면 다음과 같이 결과를 볼 수 있습니다. ^^<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > c:\temp><span style='color: blue; font-weight: bold'>mono --full-aot</span> Program.exe -402205784 -402205784 True </pre> <br /> 뭐... 어쩔 수 없군요. ^^ Mono 런타임은, AOT 빌드한 결과물에서도 역시 __makeref 처리를 하지 못합니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> Mono가 저렇다는 것은, 그에 기반을 둔 현재의 Unity가 게임 빌드 결과물에서 __makeref 처리를 못한다는 것을 의미합니다. 아마도 가장 좋은 것은 .NET Core로 Unity가 이전하는 것일 텐데 가장 최근의 결과물인 2018 버전의,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Updated scripting runtime in Unity 2018.1: What does the future hold? ; <a target='tab' href='https://blogs.unity3d.com/kr/2018/03/28/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/</a> </pre> <br /> 질문 답변을 봐도 희망이 안 보이는 것 같습니다. ^^<br /> <br /> <div style='white-space: pre-wrap; BACKGROUND-COLOR: #ccffcc; padding: 10px 10px 5px 10px; MARGIN: 0px 10px 10px 10px; FONT-FAMILY: Malgun Gothic, Consolas, Verdana; COLOR: #005555'>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.<br /> </div><br /> <br /> <hr style='width: 50%' /><br /> <br /> 참고로, clang.exe가 설치되지 않았거나 link.exe와 함께 PATH가 정상적으로 잡혀 있지 않으면 다음과 같은 식의 컴파일 오류가 발생합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C:\temp><span style='color: blue; font-weight: bold'>mono --aot Program.exe</span> 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 <span style='color: blue; font-weight: bold'>'"clang.exe"'</span> is not recognized as an internal or external command, operable program or batch file. AOT of image Program.exe failed. </pre> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
3147
(왼쪽의 숫자를 입력해야 합니다.)