[in, out] 배열을 C#에서 C/C++로 넘기는 방법 - 두 번째 이야기
지난 글에 이어서.
[in, out] 배열을 C#에서 C/C++로 넘기는 방법
; https://www.sysnet.pe.kr/2/0/810
마이크로소프트가 원래 의도한 바는 아니었겠지만, tlbimp.exe의 기능을 보정할 수 있는 방법을 별도로 제공하고 있습니다.
.NET Framework Developer's Guide
- Customizing Runtime Callable Wrappers
; https://learn.microsoft.com/en-us/previous-versions/dotnet/netframework-4.0/e753eftz(v=vs.100)
위의 글에 포함된 그림이 재미있습니다. ^^
[그림 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 개체의 이벤트를 구독하는 코드 제작
; https://www.sysnet.pe.kr/2/0/589
위의 방법 역시 interop DLL 코드가 잘못 생성된 경우인데, ildasm/ilasm 조합으로 해결할 수도 있었지 않았을까 싶네요. ^^
[이 토픽에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]