paddy
paddy

Reputation: 63481

Passing IntPtr through COM interop

How can I invoke an interface method that requires an IntPtr parameter? This is working just fine if my method requires a string, but not if it requires IntPtr. Here's an example interface in C#:

[
    Guid("etc-etc-etc"),
    InterfaceType(ComInterfaceType.InterfaceIsIDispatch),
    ComVisible(true)
]
public interface ICallback
{
    [DispId(1)]
    void CallbackWithString( string value );

    [DispId(2)]
    void CallbackWithHandle( IntPtr value );
}

I derive a COM class in C# from this interface, and pass its dispatch into my C++ application (via COM). Later on, that C++ application invokes my methods on that dispatch to provide notifications back to the C# application.

This works:

CComPtr<IDispatch> obj;      // My C# COM interop object, stored in my C++ app
VARIANT arg;

arg.vt = VT_BSTR;
arg.bstrVal = myString;
obj.InvokeN( L"CallbackWithString", &arg, 1 );

This doesn't work:

arg.vt = VT_HANDLE;          // I also tried VT_BYREF, VT_VOID|VT_BYREF, and VT_INT_PTR
arg.byref = myHandle;
obj.InvokeN( L"CallbackWithHandle", &arg, 1 );

By "doesn't work", I mean that the function is not called, but no exception is raised.

Is it possible to send an IntPtr through COM interop? If so, how?

Upvotes: 3

Views: 1265

Answers (1)

Hans Passant
Hans Passant

Reputation: 942408

Well, it's not VT_HANDLE, that's a hack from OleCtl.h. The SSCLI20 version of the CLR has its variant marshaling code in clr/src/vm/olevariant.cpp. It converts a VT_INT to IntPtr. That's however a 32-bit type, I think you'll need VT_I8 if this needs to work in 64-bit code.

Upvotes: 1

Related Questions