아주 오래 전, 거의 10년쯤 전이었을 것이다, 아래 글을 쓴 것이.


>> 참조: 비 .NET(unmanaged) 에서 호출할 수 있도록 DLL 내보내기

(블로그를 옮겨 다니느라 2008년으로 찍혀있긴 한데, 실제 글을 쓴 때는 아마 2006년쯤이었던 것으로...)



가능하다는 것만 보고, 내가 실제로 만들어 본 적은 없었는데...

이번에 어쩌다가 타 언어(Delphi)와 상호 호환되는 모듈을 각각 만들려다가,

아예 .NET DLL로 만들어서 해당 언어에서 호출해서 사용하게 만드는 것이 어떨까 싶어 도전해 봤다.


요즘 대부분의 최신 윈도우는 .NET Framework가 기본 설치되어 있기 때문에 별 무리가 없어 보였고

특히 이번에 대상으로 삼은 클라이언트 환경은 Windows 8.1 또는 Windows 10이므로

.NET Framework 4.5버전이 기본적으로 설치되어 있는 환경이라 아주 완벽한 조건이었다.




그런데,

역시... 실전은 이론과 달랐다.




일단, 그새 세월이 많이 흘렀는지 동일한 기능이 NuGet 패키지로 만들어져 있었다.

이름하여 "Unmanaged Exports (DllExports for .NET)"


>> 참조: https://www.nuget.org/packages/UnmanagedExports



해당 패키지를 설치해서 시키는 대로 DllExport 메타속성을 추가해서 빌드해 봤다.


class Test

{
  [DllExport("add", CallingConvention = CallingConvention.Cdecl)]
  public static int TestExport(int left, int right)
  {
     return left + right;
  } 
}


그랬더니,


error : syntax error at token '{' in:   {


이런 오류가 발생하면서 제대로 빌드되지 않았다.




이유를 찾아 봤더니 아무래도 빌드 환경(언어)의 문제인 듯.


>> 참조: http://stackoverflow.com/questions/20288469/cant-create-unmanaged-dll-using-c-sharp-and-robert-gieseckes-unmanaged-exports



그래서, 윈도 제어판에서 언어도 바꾸고 다시 시도해봤지만 여전히 안됐다.

(아마, 이유는 .NET SDK 또는 Visual Studio 자체가 한글판이어서였을 것 같다.)


왜 안되는지 이유를 좀 더 깊이 찾다가

NuGet 버전 말고 위 2006년판 ExportDll 도구로 한번 해 보면 어떨까 싶어 해 보니

완전히 동일한 위치에서 동일한 오류가 발생했다.


class Test

{
  [ExportDll("add", CallingConvention = CallingConvention.Cdecl)]
  public static int TestExport(int left, int right)
  {
     return left + right;
  } 
}

(ExportDll 도구를 사용할 때는 메타속성을 DllExport가 아니라 ExportDll로 써야 한다.)



알고 보니 둘은 이름만 달랐지 결국 같은 것이었던 것.

(남이 만든 것을 이런 식으로 도용해도 되나? NuGet 패키지 만든 Robert Giesecke 녀석, 은근 괘씸하다.)


그래서 ExportDll 소스코드로 아예 다시 한 줄씩 디버깅을 해봤더니, 문제가 된 부분은

ildasm 도구를 이용해서 디스어셈블된 코드(.il)의 파일 인코딩 및

코드 내에 포함된 한글 때문이라는 것을 알게 되었다.


ExportDll에서 중간언어 코드(.il)에서 몇 가지 부분을 삭제하고 치환하는 부분이 있는데

해당 부분에서 한글 인식 오류 때문에 제대로 작업이 되지 못했던 것.


일단, ildasm 도구로 뽑아낸 코드는 Encoding.Default (EUC-KR) 형식으로 파일이 저장되어 있었는데,

이것을 File.OpenText() 함수로 읽으면 UTF-8 형식으로 읽게 되므로 한글 인식이 안되는 문제가 있었던 것.


다음으로는 중간언어 코드(.il) 내에 있는 주석문 중 "// 코드 크기"라는 한글 부분이 있는데

ExportDll에서는 "// Code"라는 영문으로 검색하도록 하드코딩되어 있었기 때문에 오동작했던 것.


위 두 가지 문제를 수정해서 ExportDll 프로젝트를 다시 빌드한 뒤

NuGet 패키지 말고 ExportDll 도구를 이용해서 수작업으로 실행했더니 성공!




혹시나 해서 .NET에서 Win32 DLL 사용하는 방식대로 DllImport해 봤더니 정상 동작했다.


class Program

{

[DllImport("Test.dll", CharSet = CharSet.Auto, SetLastError = true)]

private static extern int add(int left, int right);


private static void Main()

{

int num = add(5, 3);

Console.WriteLine(num);

}

}


성공!





Posted by 떼르미
,


자바스크립트를 허용해주세요!
Please Enable JavaScript![ Enable JavaScript ]