1.VC++2008中新增加的库:Marshaling Library
我们一起讨论一下VC++2008中引入的新库——Marshaling Library。在这个类库之前我们使用的传统方法是固定指针(pin_ptr)。要使用Marshaling Library必须包含头文件<msclr"marshal.h>,使用命名空间msclr::interop,并使用marshal_as这个模板方法来执行转换,该模板方法需要两个参数,一是目标类型作为模板参数,另一个就是这个方法的参数,就是要转换的对象。如果你要把一个const wchar_t* 类型转换成String^,你可以这样写:
const wchar_t* source;
String^ dest = marshal_as<String^>(source);
一些转换需要分配内存,而且必须随后删除。这样的转换需要一个叫做context的对象,这个对象在它不再需要的时候就删除了。比如从一个托管的String^转换到本地的char*就需要一个context,因为在转换过程中生成了String的一个临时的副本。代码如下:
marshal_context context;
const wchar_t* = context.marshal_as<const wchar_t*>(str);
在这个marshaling库中预定义好了很多转换,大部分都是字符串的类型转换。你还可以根据自己的需要,自行扩展。如果有兴趣的话,可以参考MSDN。
2. 利用Marshaling Library进行互操作与以前的对比
通过一些具体的实例来看一看Marshaling Library给我们带来的便捷:
在此之前我们是通过包含<vcclr.h>头文件,引用System::Runtime::InteropServices命名空间中的Marshal类的一些方法来进行类型的转换,这些方法一方面不容易记忆,另一方面转换不直接也容易出错。比如做字符串在托管和非托管之间进行转换:
l 把托管字符串转换成ANSI字符串
String^ s = gcnew String("sample string");
IntPtr ip = Marshal::StringToHGlobalAnsi(s);
const char* str = static_cast<const char*>(ip.ToPointer());
l 把非托管ANSI字符串转换成托管字符串
void ManagedStringFunc(s) {
String^ ms = Marshal::PtrToStringAnsi(static_cast<IntPtr>(s));
}
这里的s是char*的类型,如果是const char* 的话,还需要先去掉字符串变量的常量性
const char* tempString = const_cast<char*>(s);
因为static_const无法将const char*转换成System::IntPtr。
l 转换Unicode字符串的方式与上面类似,在将const wchar_t*转换成String^类型的时候也要先去掉其常量性。
现在用Marshal库之后就可以marshal_as模板方法进行所有转换!marshal_as模板方法就提供了直接将ANSI,Unicode字符串包括进行托管和非托管转换的方法,记得要包含头文件和引用命名空间。示例代码如下:
#include <msclr/marshal.h>
using namespace msclr::interop;
l 把ANSI字符串char* ch转换成托管字符串
String^ s = marshal_as<String^>(ch);
l 把常量ANSI字符串const char* ch转换成托管字符串
String^ s = marshal_as<String^>(ch);
注意:这里就不再需要去除其常量性!
l 把托管字符串转换成非托管
marshal_context context;
return context.marshal_as<const char*>(str);
注意:这时就需要一个context上下文对象
l Unicode字符串在托管和非托管类型之间的转换和ANSI字符串的转换类似。
可以看出来,marshal_as不仅更加方便,还提供了更多的支持类型比如BSTR 和System::String^,std::string和System::String^等等。这就大大提高了开发人员的效率,使得转换信手拈来。
如果想要扩展自定义类型,从本地到托管的话只需要实现下面一个模板方法即可:
namespace msclr {
namespace interop {
template<>
inline TO marshal_as<TO, FROM> (const FROM& from) {
// Insert conversion logic here, and return a TO parameter.
}
}
}
如果需要从托管类型转换到本地类型,也是需要实现一个模板类,有兴趣的话可以参考msdn,便不在此赘述。

浙公网安备 33010602011771号