C++托管代码调用非托管代码中的封送处理
字符串
Unicode字符串
| 非托管C++ | 托管C++ |
|---|---|
| wchar_t* | String^ |
托管转非托管
- 使用PtrToStringChars 需引用< vcclr.h >
//使用pin_ptr模板阻止被垃圾回收
pin_ptr<const wchar_t> pStr = PtrToStringChars(rawString);
- 使用Marshal
IntPtr pStrPtr = Marshal::StringToHGlobalUni(rawString);
const wchar_t* pStr = static_cast<wchar_t*>(pStrPtr.ToPointer());
//最后释放掉封送到非托管内存中字符串
Marshal::FreeHGlobal(pStrPtr);
非托管转托管
用gcnew String(buff) 将wchar_t*作为构造函数参数传给String,
同时释放作为非托管函数返回的字符串内存
delete [] buff
Ansi字符串
| 非托管C++ | 托管C++ |
|---|---|
| char* | String^ |
托管转非托管
- 使用Marshal
IntPtr pStrPtr = Marshal::StringToHGlobalAnsi(rawString);
const char* pStr = static_cast<char*>(pStrPtr.ToPointer());
//最后释放掉封送到非托管内存中字符串
Marshal::FreeHGlobal(pStrPtr);
非托管转托管
用gcnew String(buff) 将char*作为构造函数参数传给String
同时释放作为非托管函数返回的字符串内存
delete [] buff
数组
封送托管C++中的数组类型:由于数组类型是托管类型,因此在传递数组作为参数调用非托管函数时,一定要防止数组被垃圾回收器回收或移动。使用pin_ptr模板阻止对数组的垃圾回收。通过向非托管函数提供GC堆中的固定指针,可避免自制数组副本的开销。
pin_ptr<int> pArray = &intArr[0];
pin_ptr指针的特性
- 锁定托管对象中的子对象等效于锁定整个托管对象
- 如果该指针被重新赋值,则原先指向的托管对象将不再被锁定
- 当指针超出作用域,则原先指向的托管对象将不再被锁定,而且也不必显式解除锁定
- pin_ptr仅允许在栈上被声时为非静态局部变量。
结构体
直接使用非托管代码中定义的结构体,传结构体的指针即可。
但当其它托管语言调用时,不能直接使用结构指针。
回调函数和委托
非托管代码中定义回调函数,托管代码中定义相应的委托
GCHandle gchDelegate = GCHandle::Alloc(func); //GCHandle可以防止委托对象被回收 func为非托管代码委托的实例
IntPtr pFunc = Marshal::GetFunctionPointerForDelegate(func);
PCallbackFunc pcbFunc = static_cast<PCallbackFunc>(pFunc.ToPointer());
gchDelegate.Free(); //最后释放掉
这时没用pin_ptr,原因:可以锁定委托对象,以防止垃圾回收器将其移动或释放,但只要保证委托对象不被回收就足够了,而并不需要将其锁定。因为垃圾回收器移动委托对象的行为并不会影响其底层的回调函数。 GCHandle.Alloc方法恰好具有防止释放而又允许移动的特点,因此使用GCHandle有助于减少托管堆上的内存碎片。
总结
在本机代码和托管代码之间进行封送处理还可以用marshal_as 方法和marshal_context类完成
如果要把非托管字符串转换为托管字符串,只需要使用
// marshal_as_test.cpp
// compile with: /clr
#include <stdlib.h>
#include <string.h>
#include <msclr\marshal.h>
using namespace System;
using namespace msclr::interop;
int main() {
const char* message = "Test String to Marshal";
String^ result;
result = marshal_as<String^>( message );
return 0;
}
本文详细介绍了C++托管代码如何调用非托管代码时进行封送处理,包括Unicode和Ansi字符串的双向转换、数组的处理、结构体的传递、回调函数和委托的应用,并强调了pin_ptr指针的角色和GCHandle在防止对象回收中的作用。总结中提及了marshal_as和marshal_context在封送处理中的应用。

1702

被折叠的 条评论
为什么被折叠?



