Marshalling C# types to call a C++ IDispatch interface results in a type mismatch

1

I'm trying to call a c++ IDispatch interface with the following method definition:

ATL HRESULT TestFunc(long Command, [in, out] long* pData, [in, out] BSTR* pString, [out, retval] long* pRC);

// ...
Type t = Type.GetTypeFromProgID( "IMyTestInterfce" );
Object so = Activator.CreateInstance(t);
Object[] args = new Object[3];               
args[0] = -8017;
args[1] = 0;
args[2] = "";
Object result = so.GetType().InvokeMember("TestFunc", BindingFlags.InvokeMethod, null, so, args);

The result from the call is a type mismatch but I'm not sure why.

InnerException = {"Type mismatch. (Exception from HRESULT: 0x80020005 (DISP_E_TYPEMISMATCH))"}`

Thanks

c#
c++
com
asked on Stack Overflow Jan 30, 2012 by probably at the beach • edited Jan 30, 2012 by probably at the beach

1 Answer

5

Your problem is that the second and third parameters (pData and pString) are marked as [in, out] in their definition, which means they translate to ref parameters in C#. You need to use the overload of InvokeMember that accepts an argument of ParameterModifier[] to specify that those argument should be passed by reference, not by value. The array of ParameterModifier should contain one element that specifies the second and third indices to be true to notate that they are passed by reference.

ParameterModifier modifier = new ParameterModifier(3);
modifier[1] = true;
modifier[2] = true;

Object result = so.GetType().InvokeMember(
    "TestFunc",                           // name
    BindingFlags.InvokeMethod,            // invokeAttr
    null,                                 // binder
    so,                                   // target
    args,                                 // args
    new ParameterModifier[] { modifier }, // modifiers
    null,                                 // culture
    null                                  // namedParameters
);
answered on Stack Overflow Jan 30, 2012 by Adam Maras

User contributions licensed under CC BY-SA 3.0