Native C/C++의 DLL을 C#에서 호출하여 사용하는 간단한 예제이다. 사용환경은 Visual Studio 2019, .NET Core 3.0을 선택하였고 모두 64bit로 빌드하였다. 주의할 점은 C++, C# 모두 x64이거나 x86으로 같이 맞추어야 에러가 나지 않는다.
C++ 64bit dll 프로젝트 생성
- 새 프로젝트 추가 : 언어 : C++
- Windows 데스크톱 마법사 → 프로젝트 이름 : Project1(임의)
- 애플리케이션 종류 : 동적 연결라이브러리(.dll)
C++ 64bit dll 프로젝트 설정
- 솔루션 탐색기 → 프로젝트 우측버튼 : 속성 선택
- 플랫폼 : x64
- C/C++ → 고급 → 호출규칙 : __stdcall(/Gz)
C++ 예제의 함수는 숫자를 반환하는 Add, 문자열을 반환하는 TestString 두 개고 작성 후 C#(.NET Core) 콘솔 프로그램에서 호출하여 사용한다. 아래는 전체 소스이다. 참고로 Project1.dll 파일은 C# 프로젝트의 실행 파일이 있는 곳에 복사한다.
전체 소스
// 기본 생성된 dllmain.cpp 하단에 아래와 같이 작성한다.
#include "pch.h"
#include <atlconv.h>
#include <stdio.h>
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
// 추가로 작성한 부분
extern "C" __declspec(dllexport) int Add(int a, int b)
{
return a + b;
}
extern "C" __declspec(dllexport) char* TestString(char* input)
{
int x = 123;
char test1[256];
sprintf_s(test1,"헬로우 : %d : ", x);
strcat_s(test1, input);
size_t stSize = strlen(test1) + sizeof(char);
char* pszReturn = NULL;
pszReturn = (char*)::CoTaskMemAlloc(stSize);
strcpy_s(_Post_ _Notnull_ pszReturn, stSize, test1);
return pszReturn;
}
// Program.cs 콘솔
using System;
using System.Runtime.InteropServices;
namespace ConsoleApp1
{
class Program
{
static void Main()
{
Console.WriteLine(ImportTest.Add(3, 4));
Console.WriteLine(ImportTest.TestString("가나닭"));
/* 결과
7
헬로우: 123 : 가나닭
*/
}
}
public static class ImportTest
{
[DllImport("Project1.dll", EntryPoint = "Add", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public static extern int Add(int a, int b);
[DllImport("Project1.dll", EntryPoint = "TestString", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
[return: MarshalAs(UnmanagedType.LPStr)]
public static extern string TestString(string input);
}
}