C#에서 C++ DLL를 사용하려면 extern 키워드를 이용해서 C++ DLL의 함수를 선언해 줘야 한다. 선언 하는 방법은 아래 코드와 같다. 만일 C#에서 pointer(*)를 넘겨야 하는 경우가 있다면 unsafe 키워드를 추가로 붙여준다.
// DllImport에 지정되는 이름은 C++ DLL의 이름과 경로를 의미한다.
[DllImport("Test.dll")]
static extern int Sum(int num1, int num2);
// *를 사용하고 있으므로 unsafe 키워드를 붙여 준다.
[DllImport("Test.dll")]
unsafe static extern bool Detect(byte* source);
int나 double 같은 기본 타입에 대해서는 알아서 변환이 되므로 일반적으로 코드를 작성하는 것처럼 사용하면 된다.
// C++ 코드
int AddInt(const int val1, const int val2)
{
return val1 + val2;
}
double MultiplyDouble(const double val1, const double val2)
{
return val1 * val2;
}
// C# 코드
int numInt = AddInt(val1: 1, val2: 2); // 결과는 3
double numDouble = MultiplyDouble(val1: 2d, val2: 0.5d); // 결과는 1
구조체는 C#과 C++에서 형식과 그 순서를 맞춰야 한다는 것만 제외하면 사용하는 법은 기본 타입과 동일하다. 우선 C++과 C#의 구조체는 다음과 같이 맞추면 된다.
// C++ 코드
struct StructSample
{
public:
StructSample(int numInt, double numDouble) : numInt(numInt), numDouble(numDouble) { }
int GetNumInt() const { return this->numInt; }
int GetNumDouble() const { return this->numDouble; }
private:
int numInt;
double numDouble;
};
// C# 코드
[StructLayout(LayoutKind.Sequential)]
struct StructSample
{
public StructSample(int numInt, double numDouble)
{
this.NumInt = numInt;
this.NumDouble = numDouble;
}
public int NumInt { get; private set; }
public double NumDouble { get; private set; }
};
C#에서 구조체에 특성으로 LayoutKind를 Sequential로 놓고 C++과 C#의 구조체 내부 순서를 맞추면 문제 없이 사용 가능하다. —class로는 안 된다.
위의 예시는 일부러 생성자와 C++에서 Get 함수, C#에서 Property를 구성하였는데, 이렇게 해도 동작 가능하다는 것을 보여주기 위해 한 것이다.
// C++ 코드
StructSample MultiplyStructure(const StructSample& input)
{
return StructSample(input.GetNumInt() * 2, input.GetNumDouble() * 2.0);
}
// C# 코드
StructSample input = new StructSample(numInt: 1, numDouble: 2d);
StructSample output = NativeMethod.MultiplyStructure(input: input); // 결과는 2, 4
C#과 C++의 string은 이름은 같지만 그 구현은 전혀 다른 것이다. 그러나 둘 다 char로 된 배열이라는 점이 같으므로 C++의 인자 쪽을 char* 타입으로 하여 C#의 string을 C++로 전달할 수 있다.
그렇게 전달 받은 char*를 C++ 내에서는 string 타입으로 변환하여 사용하면 된다.
// C++ 코드
int AddStringLength(const char* val1, const char* val2)
{
string str1(val1);
string str2(val2);
return str1.size() + str2.size();
}