C# interopservice之默认封组行为

本文详细介绍了C# interop封组器的内存管理,包括默认的封组行为,如何处理非托管内存释放,以及方向属性的影响。讨论了Blittable和Non-Blittable类型的区别,以及Copying和Pinning的概念。还探讨了格式化的Blittable类和non-blittable类在封组过程中的处理方式,展示了如何在实际代码中应用这些知识。
摘要由CSDN通过智能技术生成

参见default marshaling behaviour

interop封组器(marshaler)的内存管理

interop封组器总是会试图去释放由非托管代码分配的内存。这个行为和COM内存管理一致,但是和原生C++内存管理规则不同。

从C++中调用下面的函数不会自动释放任何内存

BSTR MethodOne (BSTR b) {
    return b;
}

注:BSTR(Basic string or binary string)是一种用于COM,Automation和Interop函数的字符串数据类型。它是一个复合数据类型,包含长度前缀,字符串和结束符。


然而,假如定义一个该函数的平台调用原型,使用String类型替换BSTR,然后调用该函数,公共语言运行库试图两次释放b的内存(第一次是当参数被传递到非托管端,第二次是从调用返回的时候)。可以通过使用IntPtr类型替代String类型来改变这种封组行为。

运行库总是使用CoTaskMemFree方法去释放内存。如果使用中的内存不是使用CoTaskMemAlloc方法分配的,就必须使用一个IntPtr来指向该内存(就不会被自动释放掉)然后再使用一个合适的方法将其手动释放掉。可以用这种方法在内存不能被释放的场合避免自动释放。

例如下面例子

C++

LPTSTR WINAPI GetCommandLine(void);

C#

[DllImport("Kernel32.dll", CharSet=CharSet.Auto)]
publicstaticextern IntPtr GetCommandLine();


[DllImport("Kernel32.dll", CharSet=CharSet.Auto)]
publicstaticextern string GetCommandLineFreeAuto();


==>C#调用

IntPtr cmdLineStr = LibWrap.GetCommandLine();
string commandLine = Marshal.PtrToStringAuto(cmdLineStr);


这里GetCommandLine返回的一段系统核心内存的数据,所以必须保证该内存段不能被自动释放,因而需要将返回类型写成IntPtr,然后再从该IntPtr指向的内存段拷贝数据。而假如使用GetCommandLineFreeAuto的话,interop封组器会去释放该string对象所表示的那块内存区域,会导致核心内存资源被释放从而导致系统问题。


方向属性

每个函数的参数都可以和InAttribute属性、OutAttribute属性或者两者关联起来。在设计函数原型的时候通过应用方向属性,可以在托管和非托管内存之间改变运行时的数据封组。


方向属性是可选的,如果想要改变封组器的默认行为的话可以将它们应用到函数参数。如果不使用方向属性,封组器通过参数的类型(值类型或引用类型)和它的修改器(如果有的话)来决定方向流向。


Visual Basic 2005

C#

IDL attribute

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值