使用COM传递数组?

时间:2008-11-17 07:39:23

标签: c++ com

我是用ATL编写的COM对象,它是从C ++应用程序中使用的,我想在两者之间传递一组BYTE。到目前为止,我对COM / IDL的体验仅限于传递简单类型(BSTR,LONG等)。

是否有一种相对简单的方法让COM对象将数组传递给调用者?例如,我想传递原始图像(TIFF)而不是弄乱临时文件。

4 个答案:

答案 0 :(得分:11)

尝试将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;
}

答案 1 :(得分:2)

如果您希望遵循OLE-Automation,可以使用SAFEARRAY,也可以使用其他语言(如VB6)的COM接口。但在IDL中有一种替代方案,例如: -

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

这描述了一种方法,其中编组代码可以通过检查第一个参数的值来推断要传输的字节数。

如果您的客户端都是用C / C ++编写的,那么这很好,但我认为包含它的接口不符合自动化,因此无法从VB6中使用,并且可能标准编组程序将无法执行编组,因此您需要从IDL生成自己的代理/存根DLL。不难做,但比使用SAFEARRAY更难。

答案 2 :(得分:0)

使用safearrays结帐。这是一些示例代码:

safearray作为指向VARIANT

的指针返回
[id(1), helpstring("LogCache")] HRESULT LogCache([out,retval] VARIANT* logCache);

安全阵列非常易于使用。这是一些示例代码,它是某些应用程序的最新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;
        }
    }

请注意,由于我使用的是comet COM library,因此您的案例中的语法几乎肯定会有所不同,但这些想法/概念是相同的。

答案 3 :(得分:-1)

您可以使用BSTR传递一个字节数组。

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

在你的方法中:

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