简体   繁体   中英

Calling managed COM from unmanaged code : SAFEARRAY

I have a COM component written in VB.net. Interface for this COM Component is

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

I am using Type Library of this COM component in Native C++ code using

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

The C++ code for Main is

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

I am able to Call FooFunc() , Foo() , Fooint() .

But I am unable to call Exec function, it doesn't show any error, no crash is reported.

For a test, I have consumed this COM component in VB.net (using CreateObject(CLSID) ) and Exec can be called from there. I need to call this from Native C++.

I suspect that there is some problem with the SafeArray and Object() conversion. Is the Interface definition wrong?

I tried with System.Array , <MarshalAs(UnmanagedType.SafeArray)> but nothing solves the problem. I have put up a MsgBox() as first statement of Exec definition so that I can know if Exec gets called.

From the suggestions given by Hans Passant I am able to use SAFEARRAY.

I am consuming Dotnet based COM component in C++. Finally I have changed the C++ code to stay safe with COM.

I have replaced VARIANT with CComVariant , BSTR with CComBSTR and SAFEARRAY with CComSafeArray .

Now the Main's code look like:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM