2008-11-17 29 views
6

ATL'de bir C++ uygulamasından kullanılan bir COM nesnesiyim ve ikisi arasında bir BYTE dizisi geçirmek istiyorum. Şu ana kadar COM/IDL deneyimim basit tiplerin (BSTR'ler, UZUNLAR, vb.) Geçmesiyle sınırlıdır.COM kullanarak bir dizi geçiriliyor?

COM nesnesinin arayana bir diziyi geçirmesinin nispeten kolay bir yolu var mı? Örneğin, geçici dosyalarla uğraşmak yerine ham bir görüntü (TIFF) iletmek istiyorum.

+10

Bir COM nesnesi olmak ne kadar eğlenceli olmalı. :-) – Danra

cevap

11

COM nesnesine bir güvenlik bloğu varyantını geçirmeyi deneyin. Böyle bir şey

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

Teşekkürler - CComSafeArray adlı çok kullanışlı bir ATL sınıfı buldum, bu da bunu çok kolaylaştırıyor (eski MFC sürümleri COleSafeArray'ı kullanabilir). – Rob

0

safearrays kullanarak kontrol edin. İşte bazı örnek kod:

Güvenli, bir VARIANT

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

bir işaretçi olarak döndürülür SAFEARRAYs kullanımı oldukça kolaydır. İşte bazı Uygulamanın en son 1000 günlük mesajlarının bir önbelleğidir bazı örnek kod:

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

senin durumda sözdizimi neredeyse kesinlikle ben comet COM library kullanıyorum çünkü farklı olacak, ama fikirlerin olduğunu Not/kavramlar aynıdır.

-1

Sen bayt dizisi geçirmek için BSTR kullanabilirsiniz .... bir SAFEARRAY varyant içinde bir bayt dizisi koymak. senin yöntemde

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

:

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

YAPMAYIN. Dizi içeriği ANSI kod sayfasından Unicode'a veya tam tersi olarak değişebilir ve ikili değerlerin değişmesine neden olabilir. İstemci uygulamaları, bu olduğunda her zaman bilmeyebilir ve verilerini bozabilirler. –

+2

Netleştirmek için: Programcı diziyi ikili veriyi tutmayı amaçlasa da, çeşitli sistem rutinleri programcının niyetini bilmez. BSTR'ler Unicode dizeleri tutmak için tasarlanmıştır ve sistem rutinleri bu varsayımı yapacaktır. –

2

SafeArrays OLE-Otomasyon uyumu isterseniz gidin ve belki böyle VB6 gibi diğer dillerden COM arayüzü kullanmak yoludur. Ancak IDL alternatif örneğin vardır: -

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

Bu manevra kod bayt sayısı birinci parametrenin değerini kontrol vasıtası ile transfer edilmesi sonucuna bir yöntemi tarif etmektedir.

müşterileriniz tüm C/C++ ile yazılmış, bu iyi, ama ben düşünmek dair bir bu, VB6 kadar değil kullanışlı otomasyon uyumlu olmaz içeren arayüz ve muhtemelen standart sıralayıcısı olmaz marshaling yapmak mümkün, bu yüzden IDL kendi proxy/stub DLL oluşturmak gerekir. Yapılması zor değil, SAFEARRAY'ları kullanmaktan biraz daha zor.

İlgili konular