【问题标题】:Calling managed COM from unmanaged code : SAFEARRAY从非托管代码调用托管 COM:SAFEARRAY
【发布时间】:2015-02-24 06:13:17
【问题描述】:

我有一个用 VB.net 编写的 COM 组件。此 COM 组件的接口是

Public Interface IEdge
    Function FooFunc() As Integer
    Function Exec(ByVal modelName As String, ByVal Params As Object()) As Object
    Sub Foo()
    Sub Fooint(ByVal a As Integer)
End Interface

我在 Native C++ 代码中使用这个 COM 组件的类型库

#import "..\Edge.tlb" named_guids raw_interfaces_only

Main 的 C++ 代码是

int _tmain(int argc, _TCHAR* argv[])
{
    HRESULT hr = CoInitialize(NULL);  //Initialize all COM Components

    ICOMEdgePtr myEdge;
    HRESULT hRes =   myEdge.CreateInstance(CLSID_COMEdge);
    if (hRes == S_OK)
    {
        VARIANT lResult ;
        BSTR str;

        myEdge->Foo();
        myEdge->Fooint(1234);
        long abc = 0;
        myEdge->FooFunc(&abc);

        SAFEARRAYBOUND aBound[2];
        aBound[1].cElements = 2;
        aBound[1].lLbound = 0;
        SAFEARRAY* sf = SafeArrayCreate(VT_INT, 1, &aBound[1]);

        long index1=0;
        int val1=20;
        SafeArrayPutElement(sf, &index1, &val1);

        long index2=1;
        int val2=30;
        SafeArrayPutElement(sf, &index2, &val2);

        myEdge->Exec(L"Add", sf, &lResult);
        //Using lResult after this  
    }

    CoUninitialize (); 
    return 0;
}

我可以致电FooFunc()Foo()Fooint()

但是我无法调用Exec函数,它没有显示任何错误,没有报告崩溃。

为了测试,我在 VB.net 中使用了这个 COM 组件(使用 CreateObject(CLSID)),并且可以从那里调用 Exec。我需要从 Native C++ 调用它。

我怀疑SafeArrayObject() 转换存在一些问题。接口定义错了吗?

我尝试了System.Array<MarshalAs(UnmanagedType.SafeArray)>,但没有解决问题。我已经提出了一个MsgBox() 作为Exec 定义的第一条语句,这样我就可以知道Exec 是否被调用。

【问题讨论】:

  • 此代码缺少所有必需的错误检查。它告诉你你做错了什么。 VTINT 的 SafeArray 仅匹配 VB.NET 中的 Integer()
  • @HansPassant Trying now for Integer()... 实际的 C++ 代码具有异常处理功能,但没有捕获任何与此相关的内容。
  • @HansPassant 使用 VT_VARIANT 而不是 VT_INT。一切正常,感谢您的帮助。

标签: c# c++ vb.net com


【解决方案1】:

根据Hans Passant 的建议,我可以使用 SAFEARRAY。

我在 C++ 中使用基于 Dotnet 的 COM 组件。最后,我更改了 C++ 代码以保证 COM 的安全。

我已将VARIANT 替换为CComVariant,将BSTR 替换为CComBSTR,将SAFEARRAY 替换为CComSafeArray

现在 Main 的代码如下所示:

int _tmain(int argc, _TCHAR* argv[])
{
    HRESULT hr = CoInitialize(NULL);  //Initialize all COM Components

    ICOMEdgePtr myEdge;
    HRESULT hRes =   myEdge.CreateInstance(CLSID_COMEdge);
    if (hRes == S_OK)
    {
        CComVariant lResult ;
        CComSafeArray<VARIANT> arr(2,0);
        arr[0] = 20;
        arr[1] = 30;

        CComBSTR methodName;
        methodName = L"Add";

        myEdge->Exec(methodName, arr, &lResult);
        wprintf(L"The result is %d\n", lResult.intVal);
        //Using lResult after this
    }

    CoUninitialize (); 
    return 0;
}

【讨论】:

    猜你喜欢
    • 2013-08-24
    • 1970-01-01
    • 2010-09-18
    • 1970-01-01
    • 1970-01-01
    • 2013-12-29
    • 1970-01-01
    • 1970-01-01
    • 2011-02-05
    相关资源
    最近更新 更多