.NET을 이용해서 C++/C 로 만든 Windows DLL들을 호출하는 방법이 있다.
그 방법은 DllImport 라고 하는 System.Runtime.InteropServices 네임스페이스의 프로퍼티 클래스를 사용하면된다.
간단한 사용예는 아래와 같다.
[DllImport("twainDSM.dll")]
private static extern TwRC DSMSetParent( [In, Out] TwIdentity origin, IntPtr zeroptr, TwDG dg, TwDAT dat, TwMSG msg, ref IntPtr refptr );
DllImport 에 원하는 DLL을 선언하고, static extern 메소드에 걸어주면 된다.
만일 입출력이 겸해지는 파라미터 인 경우 [In,Out] 을 사용하면 되고, 입력이면 그대로 [in]을 쓰면 된다.
그런데, 하나의 DLL 함수에 여러가지 형태로 정의하고 싶은 경우가 있다.
입력값이 미묘하게 틀린경우 그에 맞추기만 하면 되는 경우다.
예를 들면 TWAIN에서 제공하는 DLL 함수 중 DSM_Entry 라는 함수가 있다.
TW_UINT16 FAR PASCAL DSM_Entry( pTW_IDENTITY pOrigin,
pTW_IDENTITY pDest,
uint DG,
uint DAT,
uint MSG,
(void**) pData);
그 형태는 위와 같다. 즉 첫번째 두번째 파라미터는 규격화 된 것이지만, 맨 마지막 같은 경우에는 특정한 형태가 없는 값이다. 또, 두번째 파라미터가 null 인 경우도 있을 것이다. 호출하는 방법에 따라 그 방법이 다양한데, 이것을 C#에서는 아래와 같이 표현 할 수 있다.
[DllImport("twainDSM.dll", EntryPoint="#1")]
private static extern TwRC DSM_Entry1( [In, Out] TwIdentity origin, IntPtr zeroptr, TwDG dg, TwDAT dat, TwMSG msg, ref IntPtr refptr );
[DllImport("twainDSM.dll", EntryPoint="#1")]
private static extern TwRC DSM_Entry2( [In, Out] TwIdentity origin, IntPtr zeroptr, TwDG dg, TwDAT dat, TwMSG msg, [In, Out] TwIdentity idds );
[DllImport("twainDSM.dll", EntryPoint="#1")]
private static extern TwRC DSM_Entry3( [In, Out] TwIdentity origin, IntPtr zeroptr, TwDG dg, TwDAT dat, TwMSG msg, [In, Out] TwStatus dsmstat );
위의 첫번째 예에서 달라진 것은 EntryPoint를 명시한 것이다. 즉 DLL에서 제공하는 첫번째 메소드를 쓴다는 것이다. 함수 이름이야 뭐가 되든간에, 무조건 DLL에서 제공하는 첫번째 함수를 쓴다는 것이다. 파라미터도 최대한 DSM_Entry의 함수를 그대로 따르되, 두번째 파라미터가 Null 이라면 zeroptr에 IntPtr.Zero를 넣는 것이다. 그리고 맨 마지막 파라미터 같이 다양한 형태로 때려 박는 스타일일때는 그에 필요한 형을 그대로 집어넣는다. 그러면 .NET에서 DLL 함수와 연결할때, 알아서 해당 부분을 (void **)로써 제공할 뿐이라는 것이다. 다른 것들도 마찬가지로, 각 변수들의 크기만 잘 맞출 수 있다면 ( int 면 4바이트, short 이면 2바이트 등등) 그게 무슨 값이든 상관 없이 적용할 수 있다는 것이다.
Unmanaged .NET은 하면 할 수록 나름 매력이 솔솔 풍기는 기분이다.