先来介绍两个预处理指令:

#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 );
}
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();
}