안녕하세요. 명월입니다.
이번 글은 C++에서 Dll을 만들어 C#에서 사용하는 방법에 대한 내용입니다.
마샬링에 대한 내용은 어트리뷰트의 내용이 포함되어있습니다.
링크 - [C#] 어튜리뷰트 - (Atturibute)
우리가 C#으로 프로그램을 만들 때는 .Net Framwork 기반으로 개발합니다. 그래서 .Net Framework의 안에 있는 라이브러리와 구조를 벗어나서 개발할 수가 없습니다. 예를 들면 후크에 대해서 MSDN을 살펴보면 C#은 전역후크(Window API)를 지원 하지 않습니다. 그냥 Com+ 를 사용하라고 되어있습니다.(링크를 찾아보려 했는데 나오지 않네요.)
이럴 때는 C++의 Window Api를 가져와서 사용할 수밖에 없습니다.
또, 프로그램 언어를 C++에서 C#으로 변경할 경우, C++의 모듈을 몽땅 버리고 처음부터 다시 개발하는 것이 아니고 C++의 라이브러리는 그대로 가져와서 한개한개 개선하는 경우도 많습니다.
그럼 C++과 C#의 라이브러리를 연결하는 방법에 대해 알아보겠습니다.
먼저, C++의 DLL을 작성하겠습니다.
(저는 Visual Studio 2010의 C++ 기본 설정이 달라서 2008에서 작성하였습니다. 2010에서 사용해도 다른 점이 없습니다.)
int test1=0;
CString test2;
//외부 함수
extern "C" __declspec(dllexport) void Dll_Int_Insert(int _data)
{
test1 = _data;
printf("%d\n",test1);
}
//외부 함수
extern "C" __declspec(dllexport) int Dll_Int_Return()
{
return test1;
}
//외부 함수
extern "C" __declspec(dllexport) void Dll_String_Insert(char* _data)
{
test2.Format("%s",_data);
printf("%s\n",test2);
}
//외부 함수
extern "C" __declspec(dllexport) LPCTSTR Dll_String_Return()
{
return (LPCTSTR)test2;
}
여기서 잠깐 살펴보고 갈 내용은 C++ 과 C#은 대부분의 자료형은 같습니다. 그러나 C++를 자료형이 없으므로 약간의 형 변환이 필요합니다. String을 받을 때는 포인터로 이용한 동적 배열로 받아들리면 되겠습니다.
Return을 할 때는 LPCSTR(Long Pointer Char String) 형으로 반환을 하면 되겠습니다.
다음은 C# 코드의 마샬링 부분이겠습니다.
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace Dll_20120923_1_
{
class Program
{
//외부 함수 Import
[DllImport("Dll_20120923[0].dll")]
public static extern void Dll_Int_Insert(int _data);
//외부 함수 Import
[DllImport("Dll_20120923[0].dll")]
public static extern int Dll_Int_Return();
//외부 함수 Import
[DllImport("Dll_20120923[0].dll")]
public static extern void Dll_String_Insert(char[] _data);
//외부 함수 Import
[DllImport("Dll_20120923[0].dll")]
public static extern StringBuilder Dll_String_Return();
static void Main(string[] args)
{
//외부 함수 호출
//10을 입력하고 콘솔 창에 10출력
Dll_Int_Insert(10);
//10이 출력됨
Console.WriteLine("Dll_Int_Return : {0}",Dll_Int_Return());
//String을 char 배열 형식으로 변환한다.
//Char배열로 바꾼후 넘긴다.
//콘솔 창에 명월 출력
String _data = "명월";
char[] _data_char = _data.ToCharArray();
Dll_String_Insert(_data_char);
//메모리 타입으로 참조받음
StringBuilder SB = Dll_String_Return();
Console.WriteLine("Dll_String_Return: {0}",SB);
Console.WriteLine("Press Any key...");
Console.ReadLine();
}
}
}
어튜리뷰트로 해당 라이브러리를 취득해오고 해당 함수을 선언합니다.
String의 부분은 체크를 해야 하는데(C++은 String이 없습니다.) C++에서의 포인터로 String값을 받는 부분은 char배열(메모리 배멸)로 넘깁니다.
문제는 LPCSTR 부분인데 String도 클래스이기는 하지만 파라미터로 참조형식으로 받을 수가 없기 때문에 Stringbuilder클래스로 받아와야 합니다.
C++로 작성한 Dll를 복사해 넣겠습니다.
예제 파일 첨부합니다.
'Development note > C , C++ , MFC' 카테고리의 다른 글
[C++] C++에서 사용되는 문자열 타입(LPSTR, LPCSTR, LPCTSTR, LPCWSTR), 메모리 누수(memory leak) 체크하는 방법과 UTF8 변환하는 방법 (0) | 2020.04.17 |
---|---|
[C++] C++과 C#의 소켓 통신을 이용해 파일 전송하는 방법 (0) | 2020.04.16 |
[C++] C++과 C#의 소켓 통신을 하는 방법(문자열 송수신) (0) | 2020.04.15 |
[MFC] 서비스 프로그램 (6) | 2012.12.02 |
[C++] ShowWindow 메크로 상수, Window 메시지 상수 (0) | 2012.10.20 |
[C++] afxsock 통신 - 클라이언트편 (0) | 2012.09.30 |
[C++] afxsock 통신 - 서버편 (0) | 2012.09.30 |
[C++] ActiveX 만들기 (5) | 2012.09.14 |