Получить SAFEARRAY через IDispatch::Invoke
От: _agg  
Дата: 23.04.20 02:30
Оценка:
Есть вот такой метод COM-компоненты описанный на IDL:
        [id(0x0000001a)]
    HRESULT getParamByteArray(
                    [in] long paramId, 
                    [out, retval] SAFEARRAY(unsigned char)* value);


Изначально студия сгенерировала MFC оболочку на основе COleDispatchDriver выглядит так:
SAFEARRAY * getParamByteArray(long paramId)
{
    static BYTE parms[] = VTS_I4;
    InvokeHelper(0x1a, DISPATCH_METHOD, VT_EMPTY, nullptr, parms, paramId);
}

Это неверный код и я попытался это исправить :
 long getParamByteArray(long paramId, SAFEARRAY **parray) {
    DISPPARAMS dispparams;
    VARIANTARG varArgIn;
    VARIANTARG varArgResult;
    varArgResult.parray =*parray;
    VariantInit(&varArgIn);
    VariantInit(&varArgResult);

    V_VT(&varArgIn) = (VT_INT);
    V_VT(&varArgResult) = (VT_ARRAY | VT_UI1);

    memset(&dispparams, 0, sizeof(DISPPARAMS));
    dispparams.rgvarg = &varArgIn;
    dispparams.cArgs = 1;

    UINT nErrArg;
    EXCEPINFO excepinfo;
    HRESULT hr = m_lpDispatch->Invoke(0x1a, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &dispparams, &varArgResult, &excepinfo, &nErrArg);
    return hr;
}

Вызов данного метода:
CComSafeArray<BYTE> array(1024); 
m_error = p->getParamByteArray(param::LIBFPTR_PARAM_OFD_FISCAL_SIGN, array.GetSafeArrayPtr());

После вызова получаем S_OK и пустой массив SAFEARRAY...
Также пытался по другому инициализировать varArgResult:
V_VT(&varArgResult) = (VT_BYREF | VT_ARRAY | VT_UI1);
V_ARRAYREF(&varArgResult) = parray;

Результат тот же S_OK и пустой массив. Подскажите кто знает как правильно получить возвращаемое значение SAFEARRAY с помощью IDispatch::Invoke?
Отредактировано 23.04.2020 3:07 _agg . Предыдущая версия .
Re: Получить SAFEARRAY через IDispatch::Invoke
От: _NN_ www.nemerleweb.com
Дата: 07.05.20 09:01
Оценка:
Здравствуйте, _agg, Вы писали:

_>Есть вот такой метод COM-компоненты описанный на IDL:

_>
_>        [id(0x0000001a)]
_>    HRESULT getParamByteArray(
_>                    [in] long paramId, 
_>                    [out, retval] SAFEARRAY(unsigned char)* value);
_>


Предлагаю воспользоваться обёртками вместо ручного кода.

ATL::CComSafeArray https://docs.microsoft.com/en-us/cpp/atl/reference/ccomsafearray-class
ATL::ComQIPtr<IDispatch>
ATL::CComVariant

_variant_t

К тому же более важный вопрос раз есть IDL, то есть и TLB.
Может проще заюзать #import и получить удобный интерфейс ?
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[2]: Получить SAFEARRAY через IDispatch::Invoke
От: _agg  
Дата: 14.05.20 03:20
Оценка:
Пытался импортировать, но ругается и импорт не удается, IDL получил из OleView
Re[3]: Получить SAFEARRAY через IDispatch::Invoke
От: _NN_ www.nemerleweb.com
Дата: 14.05.20 07:03
Оценка:
Здравствуйте, _agg, Вы писали:

_>Пытался импортировать, но ругается и импорт не удается, IDL получил из OleView


На что конкретно ругается ?
Возможно есть коллизии имён и в этом случае нужно переименовать
https://docs.microsoft.com/en-us/cpp/preprocessor/rename-hash-import?view=vs-2019

Кстати, есть улучшенный OleView: https://github.com/tyranid/oleviewdotnet
http://rsdn.nemerleweb.com
http://nemerleweb.com
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.