컴퓨터/C#

[C#] C#에서 C++ DLL 사용하기

호마 2015. 6. 15. 15:16

- C# Wrapper 만들때 native c 로 구현하는 것이 귀찮아서 아래 방법을 사용함. 구조체 사용에 제약이 있음.. 

- '이 방법'을 뭐라고 부르는지 아직 모르겠음,..

- 관련어 : Pinvoke, InteropServices


- 마샬링 : 한 객체의 메모리에서의 표현방식을 저장 또는 전송에 적합한 다른 데이터 형식으로 변환하는 과정, 참고


- P/Invoke.NET Framework는 DLL 안에 패키지된 관리되지 않는 함수를 관리되는 응용 프로그램에서 호출할 수 있도록 Dllimport 특성과 함께 명시적 플랫폼 호출(PInvoke) 기능을 제공합니다. 예를 들어 Win32 함수를 호출하려면 PInvoke가 필요합니다. 자세한 내용은 C++ Interop 사용(암시적 PInvoke)을 참조하십시오. 참고


- Wrapper PInvoke를 사용하는 대신, 네이티브 .NET 데이터 형식을 사용하면서 관리되지 않는 데이터 형식과 함수를 관리되는 형식 구현의 일부로 사용할 수 있습니다. 이 경우 관리되는 코드와 관리되지 않는 코드 간의 변환은 사용자가 직접 수행해야 합니다. 참고


요약 : 마샬링하는 방법에는 PInvoke를 이용하는 것과 Wrapper를 이용하는 것 등이 있다.

즉, 아래에서 사용된 방식은 Pinvoke 를 사용하는 방법이다.

[내용 추가 - 160118]



- [참조1헐헐 '이 방식'에서 구조체 쓰는 법 https://gist.github.com/esskar/3779066



- [참조2] 이 방식에 대해 더 알아보기 http://codecooking.tistory.com/entry/C-PInvoke-ByteArray



- 사용하는 방법 코드


아래와 같이 C++ DLL을 만들어준다. 


In C++ (MyAPI.cpp)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 다음 ifdef 블록은 DLL에서 내보내기하는 작업을 쉽게 해 주는 매크로를 만드는 
// 표준 방식입니다. 이 DLL에 들어 있는 파일은 모두 명령줄에 정의된 _EXPORTS 기호로
// 컴파일되며, 다른 프로젝트에서는 이 기호를 정의할 수 없습니다.
// 이렇게 하면 소스 파일에 이 파일이 들어 있는 다른 모든 프로젝트에서는 
// MY_API 함수를 DLL에서 가져오는 것으로 보고, 이 DLL은
// 이 DLL은 해당 매크로로 정의된 기호가 내보내지는 것으로 봅니다.
#ifdef MY_API_EXPORTS
#define MY_API __declspec(dllexport)
#else
#define MY_API __declspec(dllimport)
#endif
 
namespace MyNamespace
{
#define _cplusplus // 
#ifdef _cplusplus
    extern "C" {
#endif
 
        MY_API const void* fn(const char* str);
 
#ifdef _cplusplus
    };
#endif
}
cs

- 참고 : 여기서 #define _cplusplus 내가 임의로 선언함 ㄲㄲ


 + 위의 #define "어떤 이름" __declspec 부분 정의해주기, 함수의 선언과 정의 부분 앞에 "어떤 이름" 추가

 + extern 'C' 로 함수들 묶어주기



In C# (MyAPICS.cs)

1
2
3
4
5
6
using System.Runtime.InteropServices;
 
const string MY_DLL = "MyAPI.dll"
 
[DllImport(MY_DLL, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr fn(StringBuilder str);
cs

+ InteropService 네임스페이스 정의
+ [DllImport] 부분 선언
+ 함수는 static extern 으로 선언
+ 인자 타입은 검색 ~_~

+ ..이라고 했다가 나중에 찾아옴.. 
  (추가) 마샬링 인자 타입 참고 https://msdn.microsoft.com/en-us/library/ac7ay120(v=vs.100).aspx