将使用MarshalAs(UnmanagedType.LPWStr)清理内存吗?

时间:2011-11-20 02:38:34

标签: c# pinvoke marshalling

我正在尝试为ITaskTrigger :: GetTriggerString方法编写一个pinvoke(在http://msdn.microsoft.com/en-us/library/windows/desktop/aa381866(v=vs.85).aspx定义)。如果查看页面,它会说该方法的调用者负责释放通过第一个参数引用的LPWSTR的内存(通过CoTaskMemFree)。虽然我可以在.NET中手动执行此操作,或者可以使用ICustomMarshaler编写我的自定义封送程序,但我想知道是否使用该特定参数的MarshalAs(UnmanagedType.LPWStr)属性将适当地释放内存。

任何人都可以提供一些见解吗?

1 个答案:

答案 0 :(得分:6)

首先要做的事情:你在这里谈论COM Interop(ITaskTrigger是一个COM接口),而不是P / Invoke。这两者有不同的互操作规则,因此保持它们是很重要的。例如,您需要为整个界面定义C#interop包装器,而不仅仅是您想要的方法。这些应该可以帮助您入门:pinvoke.net

简短的回答是,你很幸运,因为CLR应该妥善处理你的事情。

较长的答案涉及COM互操作代码的不同类型的编组,具体取决于参数类型,方向以及您添加到互操作签名的属性。

在这种情况下,您将在通话中获得的参数类型是“out string”参数,其中包含MarshalAs(UnmanagedType.LPWSTR)属性。当COM服务器公开一个“out”参数为LPWSTR字符串类型的调用时,假设服务器保持其交易结束,它将分配一个带有CoTaskMemAlloc()的内存缓冲区并返回它给你。 (如果它是一个不同的字符串类型,如BSTR,特定的内存分配调用可能会有所不同,但基本概念是相同的。)此时,你负责清理那个内存使用匹配的CoTaskMemFree()调用,需要更长时间。

这是一种特殊类型的操作,称为“引用更改”:您发送的参数已经是参考参数,但COM服务器将使用 替换它不同的参考。有关此过程的一个很好的解释可以在this MSDN magazine article的“内存所有权”部分找到。正如您从该文章中看到的那样,当CLR从引用类型的“out”参数接收数据时,它会识别出它正在负责释放该内存。在编组回调托管代码的同时,它使用MarshalAs属性来确定这是COM中的LPWSTR字符串类型指针,因此应该使用CoTaskMemAlloc()分配它。从数据中创建托管字符串后,它将代表您在原始缓冲区上调用CoTaskMemFree()。您获得的数据将被完全管理,您不必处理任何所有权问题。