IT정보공유/C#

c#에서 C,C++로 만들어진 DLL 사용시, 콜백함수에서 한글이 깨질때 처리 방법

알지오™ 2017. 10. 30.

c++이나 c언어로 개발된 DLL을 C#에서 이용해야 할 경우

C에 정의된 함수들을 DllImport를 통해 먼저 C#에서 선언을 해줘야 합니다.

다들 이미 아시겠지만.

일반적인 함수는 다들 아실거고 콜백 함수 부분만 설명을 드리겠습니다.

* C, C++로 개발된 DLL에 정의된 콜백함수 원형  (두번째 파라미터에서 문자열(한글)이 넘어옴)

typedef char*(*DLLCALLBACK)(char*, char*, int);

void __stdcall SetCallBack(void* a_pHandle, DLLCALLBACK a_pCallBack);


그리고 DLL 함수와 콜백을 C#에서 사용하기 위한 선언부

        public delegate void DLLCALLBACK(String Code, IntPtr Data, int Datalen);

        [DllImport("callback.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
        public static extern void SetCallBack(IntPtr pCallback, DLLCALLBACK pCallbackFunc);

        public DLLCALLBACK callback;

        //생성자든 어디든 적당한데서 콜백 생성
        callback = new DLLCALLBACK(CallbackFunc);


위 소스를 보면 delegate 정의할 때, 첫번째 파라미터는 스트링

으로 선언, 

두번째 파라미터는 IntPtr로 서로 다르게 선언했습니다. 

DLL에서는 둘다 char* 이지만 C#에서 받을 때, 한글을 받아야 하는 부분은 IntPtr로 선언해

포인터로 접근을 하기 위해서 그렇게 선언한겁니다.

C언어나 씨뿔뿔로 개발된 DLL에서 넘겨주는 콜백 파라미터를 

C#에서 String으로 받아버리면 한글 인코딩이 안됩니다. 

왜냐면 C#이 DLL에서 받는 시점에 문자열로 인식하게되어

한글이 깨진채로 인식이 되고, 

이때는 아무리 Encoding 클래스를 이용해 UTF-8이든 EUC-KR이든

변환해봐야 변환이 안되는거죠.  저도 이것 때메 이틀을 해메서 지금 이 글을 쓰고 있는겁니다.


저는 참 착합니다. 그쵸?

그럼 C#에서 포인터로 받아 버리면, 접근은 어떻게 하느냐??


        public static void CallbackFunc(String Code, IntPtr Data, int Datalen)
        {
            String strResult = "";


            byte[] RecvBytes = new byte[Datalen];

            Marshal.Copy(Data, RecvBytes, 0, Datalen);

            String Msg3 = Encoding.GetEncoding("UTF-8").GetString(RecvBytes);

        }

이렇게 마샬링이라고 하는 방법을 써야합니다. (마블링 아님)
뭐 어쨌든, 아주 간단하게 C에서 메모리 복사하듯이 직접 DLL에서 포인터로 받아 메모리 복사를 한다고
이해하시면 됩니다.

이렇게 직접 바이트로 복사를 하고나서 인코딩을 해야 한글이 깨지지 않습니다.


* DLL로 넘어온 byte배열이 c#의 string을 만나는 순간 이미 그건 문자열이 되는거라, 인코딩이 안먹어요.


이정도 설명했으면 공감 받을만 하지요?


댓글

💲 추천 글