tuto information for compiler compilador c++ com

c++ - information - Pasando una matriz usando COM?



c++ tuto (4)

Soy un objeto COM escrito en ATL que se utiliza desde una aplicación C ++, y quiero pasar una matriz de BYTE entre los dos. Mi experiencia de COM / IDL hasta ahora está limitada a pasar tipos simples (BSTR, LONGs, etc.).

¿Hay una manera relativamente fácil de hacer que el objeto COM pase una matriz a la persona que llama? Por ejemplo, quiero pasar una imagen sin formato (TIFF) en lugar de jugar con archivos temporales.


Echa un vistazo utilizando safearrays . Aquí hay un código de ejemplo:

El safearray se devuelve como un puntero a un VARIANT

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

Los Safearrays son bastante fáciles de usar. Aquí hay un código de ejemplo que es un caché de los últimos 1000 mensajes de registro de alguna aplicación:

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; } }

Tenga en cuenta que la sintaxis en su caso es casi seguro que va a ser diferente ya que estoy usando la biblioteca COM del cometa , pero las ideas / conceptos son los mismos.


Intente pasar una variante de safearray al objeto COM. Algo como esto para poner una matriz BYTE dentro de una variante de 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; }


Puede usar BSTR para pasar una matriz de bytes.

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

En tu método:

BYTE* pData = (BYTE*)bstrPassed; DWORD dataLength = SysStringByteLen(bstrPassed);


Los SAFEARRAY son el camino a seguir si desea cumplir con OLE-Automation, y tal vez usar la interfaz COM de otros lenguajes como VB6. Pero hay una alternativa en IDL, por ejemplo:

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

Esto describe un método donde el código de clasificación puede inferir el número de bytes que se transferirán inspeccionando el valor del primer parámetro.

Esto está bien si todos tus clientes están escritos en C / C ++, pero creo que una interfaz que lo contenga no sería compatible con la automatización, por lo que no se puede usar desde VB6, y posiblemente el contador de referencias estándar no pueda hacer la clasificación, por lo necesitarías generar tu propia DLL proxy / stub desde el IDL. No es difícil de hacer, pero es un poco más difícil que usar SAFEARRAY.