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

发布于 2024-12-17 01:51:49 字数 463 浏览 0 评论 0原文

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

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

I'm trying to write a pinvoke for the ITaskTrigger::GetTriggerString method (defined at http://msdn.microsoft.com/en-us/library/windows/desktop/aa381866(v=vs.85).aspx). If you look at the page, it says that the caller of the method is responsible for freeing the memory (via CoTaskMemFree) of the LPSTR referenced via the first argument. While I could do that manually in .NET or could write my custom marshaler using ICustomMarshaler, I was wondering if using the MarshalAs(UnmanagedType.LPStr) attribute for that particular argument will free the memory appropriately.

Can anyone provide some insight?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

淡看悲欢离合 2024-12-24 01:51:49

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

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

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

在这种情况下,您在调用中获得的参数类型是“out string”参数,带有 MarshalAs(UnmanagedType.LPWSTR) 属性。当 COM 服务器公开具有 LPWSTR 字符串类型的“out”参数的调用时,假设服务器正在完成其处理,它将使用 CoTaskMemAlloc( ) 并将其返回给您。 (如果是不同的字符串类型,例如 BSTR,具体的内存分配调用可能会有所不同,但基本概念是相同的。)此时,您负责清理该内存当您不再需要它时,使用匹配的 CoTaskMemFree() 调用。

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

First things first: you're talking about COM Interop here (ITaskTrigger is a COM interface), not P/Invoke. There are different interop rules for the two, so it's important to keep them straight. For example, you'll need to define C# interop wrappers for the entire interface, not just the method you want. These should get you started: pinvoke.net

The short answer is, you're in luck, becase the CLR should take care of things properly for you.

The longer answer involves the different types of marshalling the COM interop code does, depending on the parameter types, directions, and what attributes you add to your interop signatures.

In this case, the parameter type you will get on the call is an "out string" parameter, with a MarshalAs(UnmanagedType.LPWSTR) attribute. When a COM server exposes a call that has an "out" parameter of LPWSTR string type, assuming the server is keeping up its end of the deal, it will allocate a memory buffer with CoTaskMemAlloc() and return it to you. (If it was a different string type, like a BSTR, the specific memory allocation call might be different, but the basic concept is the same.) At this point, you are responsible for cleaning up that memory when you no longer need it, using the matching CoTaskMemFree() call.

This is a special type of operation called a "reference change": the parameter you are sending in is already a reference parameter, but the COM server is going to replace it with a different reference. A good explanation for this process is found in the "Memory Ownership" section of this MSDN magazine article. As you can see from that article, when the CLR receives data back from an "out" parameter on a reference type, it recognizes that it is taking responsibility for freeing that memory. While marshaling that call back to managed code, it uses the MarshalAs attribute to determine that this is a LPWSTR string-type pointer in COM, and that it should therefore have been allocated using CoTaskMemAlloc(). After creating a managed string out of the data, it will call CoTaskMemFree() on the original buffer on your behalf. The data you get back will be fully managed and you won't have to deal with any ownership problems.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文