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