У меня есть компонент COM, написанный на VB.net. Интерфейс для этого 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
Я использую библиотеку типов этого COM-компонента в Native C++, используя
#import "..\Edge.tlb" named_guids raw_interfaces_only
Код C++ для 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)
{
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
, она не показывает никаких ошибок, об авариях не сообщается.
Для теста я использовал этот COM-компонент в VB.net (используя CreateObject(CLSID)
), и Exec может быть вызван оттуда. Мне нужно вызвать это из Native C++.
Я подозреваю, что есть некоторые проблемы с SafeArray
и Object()
. Не определено ли определение интерфейса?
Я попытался использовать System.Array
, <MarshalAs(UnmanagedType.SafeArray)>
но ничто не решает проблему. Я поставил MsgBox()
как первый оператор определения Exec
чтобы я мог узнать, вызван ли Exec
.
Из предложений, предоставленных Hans Passant
я могу использовать SAFEARRAY.
Я потребляю компонент COM на основе Dotnet в C++. Наконец, я изменил код C++, чтобы оставаться в безопасности с COM.
Я заменил VARIANT
на CComVariant
, BSTR
с CComBSTR
и SAFEARRAY
с помощью CComSafeArray
.
Теперь главный код выглядит так:
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;
}