[c#] 동적으로 c++ 라이브러리 이용하기

dll 파일의 형태로 제공되는 c++ 라이브러리는 보통 정적으로 로드하여 이용하지만 동적으로 할 수도 있다. 예를 들어 라이브러리에 쿼리하는 메떠드가 있는데 10분에 100번 이렇게 이용 횟수 제한이 있을 수 있다. 이 대이터가 서버 아닌 클라이언트에 저장된다면 동적으로 로드되어 있는 라이브러리를 언로드한 뒤 다시 로드하면 이런 제한을 초기화하여 피할 수 있다.

동적으로 라이브러리를 이용하려면 윈도우즈가 제공하는 세 개의 함수들이 필요하다.

LoadLibrary*
GetProcAddress
FreeLibrary

LoadLibraryA는 안시 버전이고 LoadLibraryW는 유니코드 버전이다. 그냥 LoadLibrary라고 하면 자동으로 저들 가운데 하나를 선택하여 실행한다.

The libloaderapi.h header defines LoadLibrary as an alias that automatically selects the ANSI or Unicode version of this function based on the definition of the UNICODE preprocessor constant.
– LoadLibraryA function (libloaderapi.h)

GetProcAddress는 실행할 함수의 주소를 구한다. 동적으로 로드되는 라이브러리의 경우 컴파일을 할 때에는 그 안에 있는 함수를 특정할 수 없다. 로드를 한 뒤에야 실행할 주소를 알 수 있다.

라이브러리를 동적으로 로드한다는 건 런타임에서 FreeLibrary로 언로드할 거를 전제로 한다. 언로드할 일이 없으면 그냥 정적으로 쓸 일이다.

이들 함수들은 아래와 같이 이용한다.

[DllImport("kernel32.dll")] static extern IntPtr LoadLibraryA(string lpLibFileName);
[DllImport("kernel32.dll")] static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
[DllImport("kernel32.dll")] static extern bool FreeLibrary(IntPtr hLibModule);

IntPtr hModule = LoadLibrary(@"경로");
IntPtr address = GetProcAddress(hModule, "TestMethod");
FreeLibrary(hModule);

그런 뒤 델리개이트를 통해 라이브러리 안에 있는 함수를 위에서 구한 주소를 이용하여 포인터의 형태로 이용한다.

delegate void TestMethodDelegate();

TestMethodDelegate TestMethod;

TestMethod = (TestMethodDelegate)Marshal.GetDelegateForFunctionPointer(address , typeof(TestMethodDelegate));