先来介绍两个预处理指令:
#pragma unmanaged
#pragma managed
这两个预处理指令,控制函数编译成托管函数,还是非托管函数。是函数级别的预控制指令。
1. 托管函数传送字符串给非托管函数
分三步走
a.先调用StringToHGlobalAnsi将string转换成IntPtr类型变量,(IntPtr是Net framework用于表示指针或句柄的平台特定类型。) 这个转换过程就是将托管 String 中的内容复制到非托管内存,并在复制时转换为 ANSI 格式。此处,并不是将托管内存传递出来,而是,在非托管堆中分配内存并返回地址。所以,这块内存需要自己释放。
b.通过ToPointer方法将IntPtr实例的值转换为指向未指定的类型的指针(void *)。
c.使用完后调用FreeHGlobal 释放a步中的非托管内存。
看一个完整的例子:
//
MarshalANSI1.cpp
// compile with: /clr
#include < iostream >
#include < stdio.h >
using namespace std;
using namespace System;
using namespace System::Runtime::InteropServices;
#pragma unmanaged
void NativeTakesAString( const char * p) {
printf_s( " (native) received '%s'\n " , p);
}
#pragma managed
int main() {
String ^ s = gcnew String( " sample string " );
IntPtr ip = Marshal::StringToHGlobalAnsi(s);
const char * str = static_cast < const char *> (ip.ToPointer());
Console::WriteLine( " (managed) passing string " );
NativeTakesAString( str );
Marshal::FreeHGlobal( ip );
}
// compile with: /clr
#include < iostream >
#include < stdio.h >
using namespace std;
using namespace System;
using namespace System::Runtime::InteropServices;
#pragma unmanaged
void NativeTakesAString( const char * p) {
printf_s( " (native) received '%s'\n " , p);
}
#pragma managed
int main() {
String ^ s = gcnew String( " sample string " );
IntPtr ip = Marshal::StringToHGlobalAnsi(s);
const char * str = static_cast < const char *> (ip.ToPointer());
Console::WriteLine( " (managed) passing string " );
NativeTakesAString( str );
Marshal::FreeHGlobal( ip );
}
2. 非托管函数传递字符串给托管函数
这个简单的多了。只需要调用Marshal::PtrToStringAnsi把传统的c字符串转换成托管字符串即可。
例子:
//
MarshalANSI2.cpp
// compile with: /clr
#include < iostream >
#include < vcclr.h >
using namespace std;
using namespace System;
using namespace System::Runtime::InteropServices;
#pragma managed
void ManagedStringFunc( char * s) {
String ^ ms = Marshal::PtrToStringAnsi(static_cast < IntPtr > (s));
Console::WriteLine( " (managed): received '{0}' " , ms);
}
#pragma unmanaged
void NativeProvidesAString() {
cout << " (native) calling managed func\n " ;
ManagedStringFunc( " test string " );
}
#pragma managed
int main() {
NativeProvidesAString();
}
// compile with: /clr
#include < iostream >
#include < vcclr.h >
using namespace std;
using namespace System;
using namespace System::Runtime::InteropServices;
#pragma managed
void ManagedStringFunc( char * s) {
String ^ ms = Marshal::PtrToStringAnsi(static_cast < IntPtr > (s));
Console::WriteLine( " (managed): received '{0}' " , ms);
}
#pragma unmanaged
void NativeProvidesAString() {
cout << " (native) calling managed func\n " ;
ManagedStringFunc( " test string " );
}
#pragma managed
int main() {
NativeProvidesAString();
}