现在的位置: 首页 > 综合 > 正文

对Marshal(封送)的理解

2013年10月11日 ⁄ 综合 ⁄ 共 922字 ⁄ 字号 评论关闭

    .net Framework是强类型,自动内存回收的平台,对象存储在托管内存中,但是对象的内存布局却对开发者隐藏,甚至是不确定的。即使知道对象的内存布局,.net 也不允许直接操作托管内存,根本没提供操作内存的接口。这是一把双刃剑,对于新应用开发者这是好事,把应用开发和底层内存隔离起来,使得开发者无需了解OS以及内存布局的细节。然后现实世界远远不止.net Framework一个平台,典型的Win32平台上的程序开发者一定要知道数据在内存中的布局。因为.net Framework平台运行于Win32平台之上,所以典型的情况是,一个进程既有非托管内存,又有托管内存。这就很自然地带来了一个问题,那就是数据(对象)如何在非托管内存和托管内存中来回传递。

 

    .net Framework引入了“封送”的概念,并实现了System.Runtime.InteropServerices.Marshal类。具体看来,在非托管内存和非托管内存之间需要传递数据的情况如下:

 

(1)托管代码需要调用非托管库的函数

       这涉及到函数的参数,返回值得封送。

(2)非托管代码调用托管代码函数。

       主要是用于回调函数。

(3)托管代码直接操作非托管内存,以获得或设置非托管内存中的数据。

       如网际风股票接口,stock.dll负责接收股票数据,并存放于非托管内存中,并把数据的地址通知主程序(假设为托管程序),此时托管代码必须能够读取非托管内存中的数据。Marshal类提供了很多读取非托管内存数据的方法,但要读取结构化的数据,效率最高的还是Marshal.PtrToStructure(),该方法读取非托管内存中的数据,并根据此数据新建并初始化一个对应的托管结构体对象。看起来仿佛很简单,其实并不简单,因为托管和非托管世界里的结构体内存布局完全不同,我们需要显式修饰托管结构体,以使其封送后的内存布局与对应的非托管结构体内存布局完全相同。这需要为结构体及其成员进行封送属性的设定。

 

      暂时先写到这里,现在没有时间继续研究封送了,等完成当前最紧急的任务后,继续我的封送研究,并完成C#程序接收网际风数据的程序。(2010年10月19日)

【上篇】
【下篇】

抱歉!评论已关闭.