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 LPWSTR 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.LPWStr) attribute for that particular argument will free the memory appropriately.
Can anyone provide some insight?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With