先來(lái)介紹兩個(gè)預(yù)處理指令:
#pragma unmanaged
#pragma managed
這兩個(gè)預(yù)處理指令,控制函數(shù)編譯成托管函數(shù),還是非托管函數(shù)。是函數(shù)級(jí)別的預(yù)控制指令。
1. 托管函數(shù)傳送字符串給非托管函數(shù)
分三步走
a.先調(diào)用StringToHGlobalAnsi將string轉(zhuǎn)換成IntPtr類(lèi)型變量,(IntPtr是Net framework用于表示指針或句柄的平臺(tái)特定類(lèi)型。) 這個(gè)轉(zhuǎn)換過(guò)程就是將托管 String 中的內(nèi)容復(fù)制到非托管內(nèi)存,并在復(fù)制時(shí)轉(zhuǎn)換為 ANSI 格式。此處,并不是將托管內(nèi)存?zhèn)鬟f出來(lái),而是,在非托管堆中分配內(nèi)存并返回地址。所以,這塊內(nèi)存需要自己釋放。
b.通過(guò)ToPointer方法將IntPtr實(shí)例的值轉(zhuǎn)換為指向未指定的類(lèi)型的指針(void *)。
c.使用完后調(diào)用FreeHGlobal 釋放a步中的非托管內(nèi)存。
看一個(gè)完整的例子:
// 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 );
}
2. 非托管函數(shù)傳遞字符串給托管函數(shù)
這個(gè)簡(jiǎn)單的多了。只需要調(diào)用Marshal::PtrToStringAnsi把傳統(tǒng)的c字符串轉(zhuǎn)換成托管字符串即可。
例子:
// 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();
}