从 C# 客户端调用 C++ COM 服务器函数

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

在 C++ 上寻求有关 com 服务器的帮助。

这是调用方法的 C# 客户端代码:

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

我是这样称呼它的:

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

我总是得到 COMException: HRESULT: 0x80020008 (DISP_E_BADVARTYPE)).

C++获取方法如下:

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

以及.IDL文件接口声明:

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

编辑 1: 这是正确的代码(没有数组):

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);

谢谢。 安德鲁

OP 和我在私下讨论中设法让这个对他有用。这很可能是 proxy/stub 支持的类型的问题。我不知道所有的细节,但我知道 COM 附带的一些开箱即用的 proxy/stub 对数组的支持有限。

此外,根据我的经验,在处理互操作场景时,最好始终遵循 OLE 自动化接口的规则,如 here 所定义。如此处所示,唯一受支持的数组类型是 SAFEARRAY。这对自动化很有意义,因为 SAFEARRAYs 是唯一具有足够元数据来描述其自身内容和数组形状的标准数组类型。

不幸的是,此文档在 SAFEARRAY 方面有误或信息不足。在 COM & .NET 或 COM & VBA 之间无缝工作的唯一数组类型是 SAFEARRAY(VARIANT)。此外,我只是通过引用 (SAFEARRAY(VARIANT)*) 来实现它的工作。

综上所述,以下是对 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)