Calling C++ COM-server function from C# client

1

Looking for a help with com server on C++.

Here is C# client code to invoke method:

public static object ComInvoke(string method, params object[] args)
{
    return _comObj.GetType().InvokeMember(method, BindingFlags.InvokeMethod, Type.DefaultBinder, _comObj, args);
}

This is how I call it:

string[] result = (string[])ExplorerCore.ComInvoke("CopyFiles", new object[]{"arg1_1", "arg1_2"}, "arg2");

I always get the COMException: HRESULT: 0x80020008 (DISP_E_BADVARTYPE)).

Here is C++ getting method:

STDMETHODIMP CopyFiles(BSTR ** src, BSTR dest, BSTR ** result);

And the .IDL file interface declaration:

HRESULT CopyFiles([in, string] BSTR ** src, [in, string] BSTR dest, [out, retval] BSTR ** test);

Edit 1: This is correct code (without arrays):

C#:

string[] result = (string[])ExplorerCore.ComInvoke("CopyFiles", "arg1", "arg2");

C++

STDMETHODIMP CopyFiles(BSTR src, BSTR dest, BSTR* result);

IDL:

HRESULT CopyFiles([in, string] BSTR src, [in, string] BSTR dest, [out, retval] BSTR* test);

Thank you. Andrew

arrays
string
com
client-server
idl
asked on Stack Overflow Jul 14, 2017 by Nederes • edited Jul 14, 2017 by Nederes

1 Answer

1

OP and I managed to get this working for him in an private discussion. This is a most likely an issue of what types the proxy/stub supports. I don't know all the details, but I do know that some of the out-of-the-box proxy/stubs that ship with COM have limited support for arrays.

Moreover, in my experience, when dealing with interop scenarios, it's almost always best to follow the rules for an OLE automation interface, as defined here. As indicated there, the only type of array that's supported is SAFEARRAY. This makes sense for automation, as SAFEARRAYs are the only standard array type that have enough metadata to describe their own contents and array shape.

Unfortunately, this documentation is either wrong regarding SAFEARRAYs or not informative enough. The only type of array I've ever gotten to work seamlessly between COM & .NET or COM & VBA is SAFEARRAY(VARIANT). Moreover, I have only ever gotten this working by passing it by reference (SAFEARRAY(VARIANT)*).

All that said, here's what worked for OP:

IDL:

HRESULT CopyFiles([in] SAFEARRAY(VARIANT)* src, [in] BSTR dest, [out, retval] SAFEARRAY(VARIANT)** test);

C++:

STDMETHODIMP CopyFiles(LPSAFEARRAY src, BSTR dest, LPSAFEARRAY* result)
answered on Stack Overflow Jul 14, 2017 by Michael Gunter

User contributions licensed under CC BY-SA 3.0