Передача массива с помощью COM? - PullRequest
6 голосов
/ 17 ноября 2008

Я COM-объект, написанный на ATL, который используется в приложении C ++, и я хочу передать массив BYTE между ними. Мой опыт работы с COM / IDL ограничен передачей простых типов (BSTR, LONG и т. Д.).

Есть ли относительно простой способ заставить COM-объект передавать массив вызывающей стороне? Например, я хочу передать необработанное изображение (TIFF) вместо того, чтобы возиться с временными файлами.

Ответы [ 4 ]

11 голосов
/ 17 ноября 2008

Попробуйте передать вариант Safearray в COM-объект. Примерно так, чтобы поместить массив BYTE в вариант safearray ....

bool ArrayToVariant(CArray<BYTE, BYTE>& array, VARIANT& vtResult)
{
SAFEARRAY FAR*  psarray;
SAFEARRAYBOUND sabounds[1]; 

sabounds[0].lLbound=0;
sabounds[0].cElements = (ULONG)array.GetSize();

long nLbound;

psarray = SafeArrayCreate(VT_UI1, 1, sabounds);
if(psarray == NULL)
    return false;

for(nLbound = 0; nLbound < (long)sabounds[0].cElements ; nLbound++){
    if(FAILED(SafeArrayPutElement(psarray, &nLbound, &array[nLbound]))){
        SafeArrayDestroy(psarray);
        return false;
    }
}

VariantFree(vtResult);
vtResult.vt = VT_ARRAY|VT_UI1;
vtResult.parray = psarray;
return true;
}
2 голосов
/ 18 ноября 2008

SAFEARRAY - это лучший способ, если вы хотите совместимость с OLE-Automation и, возможно, используете интерфейс COM из других языков, таких как VB6. Но в IDL есть альтернатива, например: -

void Fx([in] long cItems, [in, size_is(cItems)] BYTE aItems[]);

Здесь описывается метод, в котором код маршаллинга может вывести число байтов, подлежащих передаче, проверяя значение первого параметра.

Это хорошо, если все ваши клиенты написаны на C / C ++, но я думаю , что интерфейс, содержащий это, не будет совместимым с автоматизацией, поэтому не может использоваться из VB6, и возможно стандартный маршалер не сможет выполнить маршалинг, поэтому вам нужно будет сгенерировать свою собственную DLL прокси / заглушки из IDL. Не сложно сделать, но немного сложнее, чем использовать SAFEARRAY.

0 голосов
/ 17 ноября 2008

Вы можете использовать BSTR для передачи массива байтов.

BYTE array[buffer_size];
...
BSTR toBePassed = SysAllocStringByteLen((OLECHAR*)array,length);
YourCOMMethod(toBePassed);
SysFreeString(toBePassed);

В вашем методе:

BYTE* pData = (BYTE*)bstrPassed;
DWORD dataLength = SysStringByteLen(bstrPassed);
0 голосов
/ 17 ноября 2008

Проверьте, используя safearrays . Вот пример кода:

Safearray возвращается как указатель на VARIANT

[id(1), helpstring("LogCache")] HRESULT LogCache([out,retval] VARIANT* logCache);

Safearrays довольно просты в использовании. Вот пример кода, который является кешем последних 1000 сообщений журнала какого-либо приложения:

   safearray_t<bstr_t> m_logCache;
   ...
   if (m_logCache.size() > 1000)
   {
       m_logCache.pop_back();
   }

   m_logCache.push_front(Msg.str(), 0);


    variant_t LogCache()
    {
        if (!m_logCache.is_empty())
        {
            variant_t cache(m_logCache);
            return cache;
        }
    }

Обратите внимание, что синтаксис в вашем случае почти наверняка будет другим, так как я использую кометную библиотеку кометы , но идеи / концепции совпадают.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...