이렇게 연타석 질문을 날리게 됐습니다....(__)
다른 회사의 SDK를 받아다가 dll로 만든 후에 닷넷 솔루션에서 사용해야하는 상황입니다.
SDK를 받아서 만들어야하는 dll 역시 C#으로 만들어야하고 64비트 빌드되어야 하는 상황입니다.
일단 SDK를 받아보니
종류별로 dll과 lib 파일이 들어 있고 문서도 함께 들어있는데요. C/C++로 만들어져 있습니다.
이걸 가지고 P/Invoke를 하려고 하는데요.
P/Invoke로 가능한 것인지 의문 나는 게 있어서 질문 드립니다.
일단 사용하고자 하는 dll의 헤더 파일을 보니
제가 호출하고자 하는 함수가 특정 Struct 안에 함수 포인터로 작성되어 있더군요.
그리고 그 Struct는 Init(params)이라는 함수를 호출해서 포인터로 넘겨받는 거구요.
간단히 일부만 예로 들면
헤더 파일에
#ifdef WIN32
#ifdef _USRDLL
#define NVSNETLIB_API EXTERN_C __declspec(dllexport)
#elif _LIB
#define NVSNETLIB_API EXTERN_C
#else
#define NVSNETLIB_API EXTERN_C __declspec(dllimport)
#endif
#else
#define NVSNETLIB_API
#endif
typedef struct CNetSession {
unsigned int dataSize;
char *recvData;
int (*sendAudio)(void *_this, char *_buf, unsigned int _size);
int (*sendControl)(void *_this, unsigned int _type, char *_buf, unsigned int _size);
} CNetSession, *pCNetSession;
NVSNETLIB_API void * NETSESSION_Init(
char *_address,
unsigned short _port,
char *_url,
char *_id,
char *_passwd,
unsigned char _connectType
);
뭐 이렇게 작성되어 있구요.
예제 소스에서는
int main(int argc, char **argv) {
pCNetSession netSession;
char connectType = 0x07;
netSession = (pCNetSession)NETSESSION_Init(argv[1], atoi(argv[2]), NULL, argv[3], argv[4], connectType );
if( netSession->sendAudio(netSession, audioBuf, dwByteRead) == 0 )
{
printf(".");
}
//
}
이런 식으로 사용하더군요.
지금 제가 호출해서 사용해야하는 함수가 sendControl이라는 함수인데
(이 함수에 대한 사용예제는 문서에 없더군요.)
이걸 C#에서 P/Invoke로 호출하려고 합니다.
일단 NETSESSION_Init()은
[DllImport("References/DLL.dll")]
public static extern IntPtr NETSESSION_Init(String _address, UInt16 _port, String _url, String _id, String _passwd, Byte _connectType);
이렇게 작성했습니다.
그리고 CNetSession Struct를 사용하기 위해
[StructLayout(LayoutKind.Sequential)]
public class CNetSession
{
public UInt32 dataSize;
public String recvData;
public delegate int sendAudio(IntPtr _this, String _buf, UInt32 _size);
public delegate int sendControl(IntPtr _this, UInt32 _type, String _buf, UInt32 _size);
}
이렇게 만들었습니다.
근데 여기서부터 이해가 잘 안 되는데요. 요약하자면
1. dll 헤더파일에 정의 되어있는 CNetSession Struct 안에 함수포인터로 작성되어 있는 것들을 C#의 클래스로 치환할 때 델리게이트로 만드는게 맞는건지?
2. 그렇다면 이 델리게이트들의 콜백은 어떻게 연결하고 호출하는지?
3. NETSESSION_Init() 메서드를 호출해서 반환 받은 IntPtr를 제가 만든 CNetSession 클래스로 변환 하는 게 가능한건지?
입니다.
SDK 문서의 사용 예제처럼, NETSESSION_Init() 함수를 호출해 반환 받은 포인터에서
직접 sendAudio() 함수를 호출하는 걸로봐서 (netSession->sendAudio() 이런 식...)
이미 dll 내부에서 sendAudio() 의 콜백을 연결 해 놓은 거 같은데 (아닌가요?)
이걸 C#에서 바로 사용할 수 있을지가 의문입니다.
(이미 콜백이 연결된 녀석인지 아니면 따로 연결을 해줘야하는 건지 모르겠습니다. 따로 연결해야한다면 어떻게 해야하나요?)
단순하게 Win32 API정도 P/Invoke 해서 쓰다가 이런 경우를 처음 마주치니까
하나도 이해가 안 되네요.
C/C++ 지식이 전무하다보니 사실 SDK에서 제공되는 예제를 봐도 이해가 잘 안 가는데,
필요한 부분만 가지고와서 P/Invoke로 쓸려니 더 이해가 안 가네요.
(예제 솔루션도 못 만들겠습니다...;ㅅ;)
혹시 질문 내용이 난해하시다면 SDK를 보내드릴게요.
답변 부탁드립니다...;ㅅ;
[최초 등록일: ]
[최종 수정일: 7/28/2011]