1. COM Interop
Dotnet CLR이 COM Interop을 위해 최적화된 마샬러(marshaler)를 제공
※ 먀샬링 :
클라이언트가 요청한 데이터를 서버가 인터페이스에 맞도록 데이터를 조직화 하고 변환하는 것.
ex) 스택
동일 어플리케이션에서 객체의 메서드를 호출할 떄 매개변수나 결과값은 스택을 통해 전달하는데,
동일한 어플리케이션이 아닐 경우 서로 다른 스택을 사용하기 때문에 전달할수 없다.
이러한 경우에 메서드를 호출하기 위해 매개변수와 결과값은 바이트 스트림(메모리버퍼)에 기록하고 전달하는 방법으로 해결할 수 있는데
바이트 스트림으로 변환하는 과정을 마샬링이라 한다.
2. PInvoke(Platform Invoke)
DLL이 외부에 노출하는 export 함수를 직접 호출하는 방법
※ Marshaling PInvoke : http://msdn.microsoft.com/en-us/library/fzhhdwae.aspx
ex) win32 dll Import code
[DllImport("kernel32.dll")]
private static extern uint GetCurrentProcessId();
public Form1()
{
InitializeComponent();
string msg = String.Format("Current Process ID : {0}", GetCurrentProcessId());
MessageBox.Show(this, msg, "", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
2-1. 문자열
Dotnet환경에서는 GC에 의해서 힙에 할당된 메모리가 해제될 때, 최적화를 위해 힙에 해제되지 않은 메모리를 컴팩하기 때문에 객체의 위치가 변경될 수 있음.
C#에서 GC에게 메모리의 위치를 고정시킬 것이라는 명시(fixed)를 함으로써 해결한다.
fixed 키워드를 사용하려면 프로젝트의 속성의 '빌드' 설정에서 안전하지 않은 코드 허용을 설정해주어야 한다.
ex1) C++ 함수
namespace export1 {
public ref class Class1
{
public :
static void UnmanagedFunc(unsigned char* str)
{
std::cout << "string : " << str << std::endl;
str[0] = 'V';
}
// TODO: 여기에 이 클래스에 대한 메서드를 추가합니다.
};
}
ex2) C#에서 C++ 모듈 함수 호출 string inputData = "testStr";
byte[] inputByteData = System.Text.Encoding.Default.GetBytes(inputData);
unsafe
{
fixed (byte* aa = &inputByteData[0])
{
export1.Class1.UnmanagedFunc(aa);
}
}
string output = System.Text.Encoding.Default.GetString(inputByteData);
-> 결과값 : VestStr
- 주의사항 : 매개변수를 전달하기 위해서는 데이터 타입을 일치시켜야 한다. 동일한 표현이 아닐수 있기 때문에 아래의 타입을 확인한다
※ Marshaling PInvoke Data Types : http://msdn.microsoft.com/en-us/library/ac7ay120.aspx