관련글
c++ DLL을 C#에서 사용해보자 ( 함수 마샬링 )
c++ DLL을 C#에서 사용해보자 ( 클래스 마샬링 )
*Window XP 32bit 기준입니다.*
머......피치못할 사정으로 c++로 작성된 dll을 써야 된다면.....명복을 크크크크크크크
하지만 어차피 c++ dll은 여러모로 쓸모가 많다 보니 재판매(?)를 어느 정도 고려 할 겸, 역어셈에도 닷넷보다는 안전해 보여서 dll은 c++로 만들어 쓸 때가 있습니다.
근데 이렇게 딴 언어에서 만든 dll을 쓰기 위해서 마샬링이 필요합니다. ㅡ,.ㅡ;;;
일종의 컨버전이라고 생각하면 됩니다.
쉽게 생각하라고 컨버전이라고 한 거지 전혀 다릅니다.
컨버전은 프로그램 자체를 다른 언어에 맞게 변경시키는 것을 의미하고. 마샬링은 다른 언어에서도 읽을 수 있게 해주는 작업입니다.
마샬링은 dll자체는 변하지 않는다는 거~
마샬링하는 방법은 여러 가지가 있고 dll불러다 쓰는 방식도 여러 가지가 있으나 편의상 하나만 ㅎㅎㅎ
(절대 귀찮은 거 아니라능)
일단 자주 쓰는 것들만 해봅시다.
먼저 C++로 dll을 만들어 봅시다.
이거 안 해놓으면 고생 많이 합니다 ㅎㅎㅎ
#include <windows.h>
typedef struct tTest
{
char strTest[128]; //문자열 128
int intTest; //숫자형
BYTE byteTest[64]; //바이트형 배열
UINT uintTest[4]; //유니트형 배열
} typeTest;
//기본형
extern "C" __declspec(dllexport) void OnTest1(void);
//입출력 숫자형
extern "C" __declspec(dllexport) int intOnTest2(int intTemp);
//입출력 문자열형
extern "C" __declspec(dllexport) char* strOnTest3(char *strTemp);
//입력 구조체(포인터 출력가능)
extern "C" __declspec(dllexport) void OnTest4(typeTest *testTemp);
//입출력 배열(포인터 출력가능)
extern "C" __declspec(dllexport) void OnTest5(int *intTemp);
#include "claTest.h"
void OnTest1(void)
{
//기본형
}
int intOnTest2( int intA)
{
//입출력 숫자형
++intA; //입력받은 숫자에 +1
return intA;
}
char* strOnTest3(char *strTemp)
{
//입출력 문자열형
static char strTemp2[128] = {0,}; //임시저장용 문자열
sprintf_s( strTemp2, "%s strOnTest3 에서 리턴", strTemp); //문자열 합치기
return strTemp2;
}
void OnTest4( typeTest *testTemp )
{
//입력 구조체형(포인터 출력가능)
testTemp->byteTest[0] = 1;
testTemp->intTest = testTemp->intTest + 2;
sprintf_s( testTemp->strTest, "%s OnTest4에서 포인터", testTemp->strTest);
testTemp->uintTest[0] = 1;
}
void OnTest5(int *intTemp)
{
//입출력 배열형(포인터 출력 가능)
for( int i = 0 ; i < 10 ; ++i )
{
intTemp[i] = intTemp[i] + i;
}
}
빌드하고 dll의 위치를 알아서 정하시면 되겠습니다.
테스트하기 좋게 이렇게 만들었습니다.
1이라고 적혀있는 텍스트박스가 textBox2, 그 아래가 textBox1 입니다.
버튼은 위에서부터 button1, button2, button3, button4 입니다.
클래스 안에 넣어야 합니다,
구조체는 dll에 넣고 뺄 때만 사용하기 때문에 그때만 양쪽의 형식이 맞으면 되니 알아서들 잘 쓰시고 여기 나와 있는 건 규격이라고 생각하면 됩니다.
public struct typeTest
{
//문자열 124
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public String strTest;
//숫자형
public int intTest;
//바이트 배열
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
public byte[] byteTest;
//유니트형 배열
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public UInt32[] uintTest;
}
당연한 이야기지만 [DllImport("dll경로 및 이름")] 입니다.
여기서는 함수의 입출력 타입이 정확해야 합니다.
[DllImport("test1.dll")]
extern public static void OnTest1();
[DllImport("test1.dll")]
extern public static int intOnTest2(int intTemp);
[DllImport("test1.dll")]
extern public static string strOnTest3(string strTemp);
[DllImport("test1.dll")]
extern public static void OnTest4(ref typeTest testTemp);
[DllImport("test1.dll")]
extern public static void OnTest5(int[] intTemp);
이렇게 하면 됩니다.
private void button1_Click(object sender, EventArgs e)
{
OnTest1();
}
private void button2_Click(object sender, EventArgs e)
{
MessageBox.Show(intOnTest2(int.Parse(textBox2.Text)) + " = intOnTest2(" + textBox2.Text + ")");
}
private void button3_Click(object sender, EventArgs e)
{
MessageBox.Show(strOnTest3(textBox1.Text) + " = strOnTest3(" + textBox1.Text + ")");
}
private void button4_Click(object sender, EventArgs e)
{
typeTest testTemp = new typeTest();
testTemp.byteTest = new byte[64];
testTemp.uintTest = new uint[4];
testTemp.strTest = textBox1.Text;
testTemp.intTest = int.Parse(textBox2.Text);
testTemp.byteTest[0] = byte.Parse(textBox2.Text);
testTemp.uintTest[0] = uint.Parse(textBox2.Text);
OnTest4(ref testTemp);
MessageBox.Show(textBox1.Text + " => " + testTemp.strTest + "\r\n"
+ textBox2.Text + " => " + testTemp.intTest + "\r\n"
+ textBox2.Text + " => " + testTemp.byteTest[0] + "\r\n"
+ textBox2.Text + " => " + testTemp.uintTest[0] + "\r\n"
);
}
private void button5_Click(object sender, EventArgs e)
{
int[] intTemp = new int[5];
intOnTest5(intTemp);
MessageBox.Show( intTemp[0] + "\r\n"
+ intTemp[1] + "\r\n"
+ intTemp[2] + "\r\n"
+ intTemp[3] + "\r\n"
+ intTemp[4] + "\r\n"
);
}
이제 버튼을 눌러 봅시다~
잘 돌아 가네요.
마샬링은 여러 가지로 힘든 작업입니다.-_-;;;
귀찮기도하고...
아마도 처음에 기획만 제대로 해도 쓸 일이 많지 않을 겁니다. ㅋㅋㅋㅋ
마샬링에 관한 변수 타입에 대하 설명이다. 참고하도록 합니다!
참고 : http://msdn.microsoft.com/en-us/library/ac7ay120.aspx
p.s. 저는 유니트형과 바이트형을 자주 안 쓰다 보니..... 두 개 사용법이 틀렸을 수도 있습니다 ㅡ.-;