Re[2]: На VB всё работает, на VC++ одна функция не работает
От: avk-75  
Дата: 14.10.05 16:22
Оценка:
Здравствуйте, 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, &params, &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, &params, &varResult, NULL, NULL);


В res, правда, возвращается какой-то exception , но функция отрабатывает – я это знаю точно (иначе, если бы туда передавались бы некорректные строки, на экран бы выдавалось окошко с полями для ввода логина и пароля).
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.