728x90
[in, out] 배열을 C#에서 C/C++로 넘기는 방법 - 두 번째 이야기



지난 글에 이어서.

[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 생성 방법]
how_to_customize_rcw_1.gif

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


728x90

+ Recent posts