지난 글에 이어서.
[in, out] 배열을 C#에서 C/C++로 넘기는 방법 ; http://www.sysnet.pe.kr/Default.aspx?mode=2&sub=0&detail=1&wid=810
마이크로소프트가 원래 의도한 바는 아니었겠지만, tlbimp.exe 의 기능을 보정할 수 있는 방법을 별도로 제공하고 있습니다.
.NET Framework Developer's Guide - Customizing Runtime Callable Wrappers ; http://msdn.microsoft.com/en-us/library/e753eftz.aspx
위의 글에 포함된 그림이 재미있습니다. ^^
[그림 1: RCW DLL 생성 방법]
RCW를 생성하는 3가지 방법 중에서 중간 그림이 의미가 있는데, 일단 한번 tlbimp.exe에 의해서 생성된 DLL 을 역어셈블한 뒤, 원하는 데로 마샬링 정보를 바꾸고 다시 ilasm을 이용해서 DLL을 생성하고 있습니다. 오호... 이 정도면 훌륭한 대안이죠. ^^
이것을 이용해서 지난 번 예제를 개선해 보겠습니다.
IDL 은 원래 정의된 그대로 사용하고,
[ object, uuid(1A38076B-3D6D-4F20-8B4D-C72EF6AE1204), dual, nonextensible, helpstring("IMyTest Interface"), pointer_default(unique) ] interface IMyTest : IDispatch { [id(0x3003), helpstring("method PrepareBuf")] HRESULT PrepareBuf([in, out, size_is(bufLength)] __int64 buffer [], [in] int bufLength); };
마샬링 정보가 올바르진 않겠지만 일단 tlbimp.exe (또는 Visual Studio의 DLL 참조)를 이용하여 interop DLL을 생성합니다.
tlbimp testatl.dll /out:interop.testatl.dll
ildasm 으로 DLL을 역어셈블하면 해당 메서드가 다음과 같이 선언된 것을 볼 수 있습니다.
ildasm interop.testatl.dll /out:interop.testatl.il .method public hidebysig newslot virtual instance void PrepareBuf([in][out] int64& buffer, [in] int32 bufLength) runtime managed internalcall { .custom instance void [mscorlib]System.Runtime.InteropServices.DispIdAttribute::.ctor(int32) = ( 01 00 03 30 00 00 00 00 ) // ...0.... .override interop.testatl.IMyTest::PrepareBuf } // end of method MyTestClass::PrepareBuf
여기에서 "[in][out] int64& buffer" 구문을 "[in][out] int64[] marshal([]) buffer" 과 같이 바꿔줍니다. (또 한군데 더 정의되어 있기 때문에 그 부분도 마저 바꿔줍니다.) 이렇게 변경하고 다시 ilasm으로 어셈블해주면, C# 에서 정상적으로 long [] 으로 사용할 수 있습니다.
ilasm interop.testatl.il /dll public virtual void PrepareBuf(long[] buffer, int bufLength);
우와~~~ ^^ 깔끔하죠! (첨부된 파일은 위의 예제와 지난 번 글의 예제를 함께 테스트한 프로젝트입니다.)
그러고 보니, 이걸 하면서 예전에 쓴 글이 하나 생각났습니다.
COM 개체의 이벤트를 구독하는 코드 제작 ; http://www.sysnet.pe.kr/Default.aspx?mode=2&sub=0&detail=1&wid=589
위의 방법 역시 interop DLL 코드가 잘못 생성된 경우인데, ildasm/ilasm 조합으로 해결할 수도 있었지 않았을까 싶네요. ^^
출처 : http://www.sysnet.pe.kr/2/0/811
'Basic Programming > CLI' 카테고리의 다른 글
CLI - 배열을 C#에서 C/C++로 넘기는 방법 (1/2) (0) | 2018.10.10 |
---|---|
CLI - 제공되는 명시적인 파괴자의 비밀 (0) | 2018.10.08 |
CLI - Native C++ 개발자를 위한 C++/CLI (0) | 2018.10.02 |