Is it safe to use COM Callable Wrapper to avoid problems passing GCHandles across app domains?

There is a relatively well-known issue in .NET with storing managed objects in unmanaged code as a way gcroot<ManagedObject>

to provide callbacks from unmanaged code: unmanaged code doesn't know what AppDomain should use when called into managed code, and sometimes it picks the wrong one, which leads to errors. " Unable to pass GCHandle through AppDomains ".

The standard solution to the problem is to use a function pointer to the delegate, since the delegate can be used to "remember" the correct AppDomain: see http://lambert.geek.nz/2007/05/29/unmanaged-appdomain-callback/ for a full explanation.

However, this decision is a little more complicated and requires careful management of the tar's lifetime.

It seems that using the COM-Callable Wrapper for the managed object works just as well: instead of saving gcroot<ManagedObject>

, store the pointer as IUnknown *

with GetIUnknownForObject

:

m_value =
   static_cast<IUnknown*> (Marshal::GetIUnknownForObject(value).ToPointer());

      

We can then do the reverse translation with GetObjectForIUnknown

before executing the callback. The disadvantage loses a bit of type safety because it IUnknown *

loses the actual type of the object and you have to dump later using something like

IDisposable^ value =
      (IDisposable^) (Marshal::GetObjectForIUnknown(IntPtr(m_value)));

      

where m_value

- IUnknown*

, but it seems like a small price to pay.

I tried this and it seems to work fine in my use case, but are there any problems with this approach? This seems to apply wherever a delegate solution could be used, so I wonder if I'm missing something on this.

+3


source to share


1 answer


I've been using this approach in production for several months without any problems, so while it's not entirely definitive, I'm going to tentatively conclude that this approach is safe.



0


source







All Articles