2008-11-17 2 views
6

Ich bin ein COM-Objekt in ATL geschrieben, die aus einer C++ - Anwendung verwendet wird, und ich möchte ein Array von BYTEs zwischen den beiden übergeben. Meine bisherigen Erfahrungen mit COM/IDL beschränken sich auf die Weitergabe einfacher Typen (BSTRs, LONGs usw.).Ein Array mit COM übergeben?

Gibt es eine relativ einfache Möglichkeit, das COM-Objekt ein Array an den Aufrufer übergeben? Zum Beispiel möchte ich ein Rohbild (TIFF) übergeben, anstatt mit temporären Dateien zu spielen.

+10

Wie lustig es sein muss, ein COM-Objekt zu sein. :-) – Danra

Antwort

11

Versuchen Sie, eine Safearray-Variante an das COM-Objekt zu übergeben. So etwas wie dies ein Byte-Array in einer Safearray-Variante setzen ....

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

Danke - Ich fand eine sehr nützliche ATL-Klasse namens CComSafeArray, die dies sehr einfach macht (ältere Versionen von MFC können COleSafeArray verwenden). – Rob

0

Auschecken mit safearrays. Hier einige Beispiel-Code:

Der Safearray wird als Zeiger auf eine VARIANT zurückgegeben

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

Safearrays sind ziemlich einfach zu bedienen. Hier einige Beispiel-Code, der einen Cache der letzten 1000 Protokollmeldungen von einigen Anwendungen ist:

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

Beachten Sie, dass die Syntax in Ihrem Fall ist mit ziemlicher Sicherheit anders sein werde, da ich die comet COM library bin mit, aber die Ideen/Konzepte sind gleich.

-1

Sie können BSTR verwenden, um ein Array von Bytes zu übergeben.

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

In Ihrer Methode:

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

TUN SIE NICHT. Der Array-Inhalt wird möglicherweise von der ANSI-Codepage in Unicode oder umgekehrt übersetzt, wodurch sich die Binärwerte ändern. Clientanwendungen wissen möglicherweise nicht immer, wann dies geschieht, und sie werden feststellen, dass ihre Daten beschädigt sind. –

+2

Zur Klarstellung: Obwohl der Programmierer beabsichtigt, dass das Array binäre Daten enthält, kennen verschiedene Systemroutinen die Absicht des Programmierers nicht. BSTRs sollen Unicode-Zeichenfolgen enthalten, und Systemroutinen werden diese Annahme vornehmen. –

2

Safearrays sind der Weg zu gehen, wenn Sie OLE-Automation Compliance wollen, und vielleicht die COM-Schnittstelle aus anderen Sprachen wie VB6 zu verwenden. Aber es gibt eine Alternative in IDL, zum Beispiel: -

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

Dies beschreibt ein Verfahren, bei dem der Rangier-Code der Anzahl von Bytes ableiten kann durch Überprüfen des Wertes des ersten Parameters übertragen werden.

Das ist in Ordnung, wenn Ihre Kunden alle in C/C++ geschrieben sind, aber ich denke, dass eine Schnittstelle dieser Automatisierung konform wäre nicht enthalten, werden so nicht verwendbar von VB6 und möglicherweise der Standard Marshaler nicht in der Lage sein, das Marshalling durchzuführen, also müssten Sie Ihre eigene Proxy/Stub-DLL von der IDL generieren. Nicht schwer zu tun, aber ein bisschen härter als die Verwendung von SAFEARRAYs.