科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道浅谈.NET互操作技术 重点托管代码

浅谈.NET互操作技术 重点托管代码

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

4. 因为非托管代码的调用方式为_cdecl, 所以托管部分的CallingConvention需要设置为CallingConvention.Cdecl,另外这种类型的调用方式是调用方负责处理堆栈,所以支持可变类型参数函数例如printf()的互操作。

来源:autocad2008博客 2010年4月23日

关键字: 网络

  • 评论
  • 分享微博
  • 分享邮件

  多年来在程序设计领域微软技术一直引领着每个时代,在每一代的技术背后都有相关的动机,而这些动机及其实现细节往往是大部分的程序设计课程没有涉及的,但是对于我们理解相关的技术又十分重要,本文将对几种相关技术和隐藏在动机背后的细节做简要的阐述,算是抛砖引玉。

  COM技术于1993年首次发布,称得上是微软技术的一个里程碑,其意义在于使组件编程化得以实现。COM技术最初的思想起源于将类做成可重用的二进制组件,把类的实现和接口分离以便把类的实现封装到二进制防火墙的背后,而这道防火墙以VPTR和VTBL的形式保证了这个防火墙的不变性。.NET技术则在语言层面上支持了基于组件的程序设计。相对于COM技术,.NET技术就是为基于组件的程序设计而生的,所以其编码效率和语言可读性要高出COM一个等级。但是由于1993年以后的十多年时间里,人们利用基于COM的组件程序设计技术开发了大量的高复杂度,高可用性的代码,并且他们运行良好,效率极高,如果用.NET技术重写这些代码简直就是得不偿失,加之在.NET的实现过程中并不是所有的Windows API都被重写,有些功能是.NET所不能完成的。面对这样的问题, .NET互操作技术应运而生,可见需求才是技术的原动力。

  .NET互操作技术主要分为3种,P/Invoke,C++ Interop,COM Interop,其中P/Invoke 主要用于调用C库函数和Windows API。C++ Interop则主要用于Managed C++调用 C++类库和核心算法库,它甚至允许托管代码和非托管代码在同一个文件中。 COM Interop主要包括正向的RCW和反向的CCW。下面以一个简单的例子对互操作中比较重要的数据封送进行简单的介绍。

  如何封送字符串(P/Invoke方式)

  假设非托管代码定义如下:

  void _cdecl stringMarshal( constwchar_t*inString, wchar_t*outString, intbuffersize) { If(NULL !=inString) { wcscpy_s(outString, buffersize, inString); } }

  这段代码编译生成的文件名为:stringMarshal.dll

  在托管代码中其托管定义如下:

  [DllImport (“stringMarshal.dll”, CharSetCharSet =CharSet.Unicode, CallingConventionCallingConvention =CallingConvention.Cdecl) ] publicextern static void stringMarshal (stringinString, StringBuilder outString, intbufferSize);

  这里有几点需要注意:

  1. 在声明函数时必须要用extern修饰符,目的是为了告诉编译器此函数是外部实现的,没有方法体,因此不需要在托管代码中搜索这个函数。

  2. 在声明函数时必须要用static修饰符,原因是非托管的DLL导出的非托管方法都是可以直接调用的,无需对相关的类进行实例化,大部分情况下根本就不存在类。

  3. 因为非托管代码中的字符串为wchar_t*类型,所以CharSet需要设置为CharSet.Unicode。

  4. 因为非托管代码的调用方式为_cdecl, 所以托管部分的CallingConvention需要设置为CallingConvention.Cdecl,另外这种类型的调用方式是调用方负责处理堆栈,所以支持可变类型参数函数例如printf()的互操作。

  5. 输入字符串需要封装为string是因为这个字符串属于固定字符串,互操作过程中不需要变化,而输出字符串则需要封装为StringBuilder,因为这种字符串默认为具有IN/OUT属性,其内容可变,而且当字符串经常需要变化时效率高。

  托管代码中调用非托管代码方式如下:

  privatestaticvoid TestStringMarshal () { stringinString ="Wally input test string."intbufferSize =inString.Length; StringBuilder strbd =newStringBuilder(bufferSize); stringMarshal (inString, strbd, bufferSize +1); Console.WriteLine("Wally Input string: {0}", inString); Console.WriteLine("Wally output string: {0}", strbd.ToString()); }

  总结

  本文简要的介绍了.NET托管代码和本地非托管代码的互操作技术,并对数据封送的实现细节做了简单的说明,希望对大家的技术提高有所帮助,算是抛砖引玉,期待大家在这方面写出更多更好的文章。

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章