Здравствуйте, slava_529872, Вы писали:
>Пришли сигнатуру метода (из IDL)...
IDL по-моему нет… (вообще-то я новичок в COM, но все же, как мне кажется, основные принципы понимаю). Может так быть?
>...и как ты его вызываешь!
Вот код на VB (это работает):
Dim locClassName As String
Dim locMethodName As String
Dim locParams As String
Dim Err As String
Set Test = CreateObject("<ObjectName>")
Err = Test.Login("username", "password")
locClassName = "tOrder"
locMethodName = "USRPSetFF_TST"
locParams = ""
Err = Test.CallClassMethod(locClassName, locMethodName, locParams, 1)
Err = Test.ShutdownBOleSrv()
Set Test = Nothing
===============================================================================================================
Вот, как метод описан в документации:
long CallClassMethod(string parClassName, string parMethodName, string* parMethodParams, long parMessageMode)
===============================================================================================================
Вот как я пытаюсь вызвать из VC++:
HRESULT res;
LPOLESTR str3 = OLESTR("CallClassMethod");
wchar_t locClassName[] = L"tOrder";
BSTR locBSTR_ClassName = ::SysAllocString(locClassName);
wchar_t locMethodName[] = L"USRPSetFF_TST";
BSTR locBSTR_MethodName = ::SysAllocString(locMethodName);
wchar_t locNullStr_Smp[] = L"";
BSTR locBSTR_NullStr_Smp = ::SysAllocString(locNullStr_Smp);
VARIANTARG varg[4];
::VariantInit(varg);
VARIANT varResult;
DISPPARAMS params;
varg[0].vt = VT_BSTR;
varg[0].bstrVal = locBSTR_ClassName;
varg[1].vt = VT_BSTR;
varg[1].bstrVal = locBSTR_MethodName;
varg[2].vt = VT_BYREF | VT_BSTR;
varg[2].pbstrVal = &locBSTR_NullStr_Smp;
varg[3].vt = VT_I4;
varg[3].lVal = 1;
VariantClear(&varResult);
params.cArgs = 4;
params.rgvarg = varg;
params.cNamedArgs = 0;
params.rgdispidNamedArgs = NULL;
pDisp->GetIDsOfNames(IID_NULL, &str3, 1, LOCALE_SYSTEM_DEFAULT, &dispid);
res = pDisp->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, ¶ms, &varResult, NULL, &argerr);
::SysFreeString(locBSTR_ClassName);
::SysFreeString(locBSTR_MethodName);
::SysFreeString(locBSTR_NullStr_Smp);
res возвращает 0x80020005, что, согласно WINERROR.H означает DISP_E_TYPEMISMATCH – несоответствие типов. Написано, что argerr при этом должен возвращать индекс аргумента, вызвавшего ошибку. В аrgerr возвращается 0x00000000. Ошибка в 1-ом параметре? Но функция Login, также принимающая строки, отрабатывает корректно, вот как я ее зову из VC++ (кусок той же программы):
HRESULT res;
LPOLESTR str = OLESTR("Login");
wchar_t locNullStr_UserName[] = L"username";
BSTR locBSTR_NullStr_UserName = ::SysAllocString(locNullStr_UserName);
wchar_t locNullStr_Password[] = L"password";
BSTR locBSTR_NullStr_Password = ::SysAllocString(locNullStr_Password);
VARIANTARG varg[4];
::VariantInit(varg);
VARIANT varResult;
DISPPARAMS params;
varg[0].vt = VT_BSTR;
varg[0].bstrVal = locBSTR_NullStr_UserName;
varg[1].vt = VT_BSTR;
varg[1].bstrVal = locBSTR_NullStr_Password;
VariantClear(&varResult);
params.cArgs = 2;
params.rgvarg = varg;
params.cNamedArgs = 0;
params.rgdispidNamedArgs = NULL;
pDisp->GetIDsOfNames(IID_NULL, &str, 1, LOCALE_SYSTEM_DEFAULT, &dispid);
res = pDisp->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, ¶ms, &varResult, NULL, NULL);
В res, правда, возвращается какой-то exception
, но функция отрабатывает – я это знаю точно (иначе, если бы туда передавались бы некорректные строки, на экран бы выдавалось окошко с полями для ввода логина и пароля).