托管和非托管转换新方法:Marshaling Library

托 管和非托管转换新方法:Marshaling Library

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类的一些方法来进行类型的转换,这些方法一方面不容易记忆,另一方面转换不直接也容易出错。比如做字符串在托管和非托管之间进行转换:

把 托管字符串转换成 ANSI字符串

String^ s = gcnew String("sample string");

   IntPtr ip = Marshal::StringToHGlobalAnsi(s);

   const char* str = static_cast<const char*>(ip.ToPointer());

把非托管 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 ;

ANSI字符串 char* ch转换成托管字符串

String^ s = marshal_as <String ^>(ch );

把 常量 ANSI字符串 const char* ch转换成托管字符串

String^ s = marshal_as<String^>(ch);

注意:这 里就不再需要去除其常量性!

把 托管字符串转换成非托管

    marshal_context context ;

    return context.marshal_as<const char*>(str);

         注意:这时就需要一个 context 上下文对象

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,便不在此赘述。

=================================================================================================================

备注:

1. using namespace msclr::interop;和 //using namespace System::Runtime::InteropServices; 定义上有重。所以用其中一种

2. #include <msclr/marshal_atl.h>中的“ msclr/”要加

3. “Overview of Marshaling in C++”有转换对应表 http://msdn.microsoft.com/zh-cn/library/bb384865(v=VS.90).aspx

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值