我是用ATL编写的COM对象,它是从C ++应用程序中使用的,我想在两者之间传递一组BYTE。到目前为止,我对COM / IDL的体验仅限于传递简单类型(BSTR,LONG等)。
是否有一种相对简单的方法让COM对象将数组传递给调用者?例如,我想传递原始图像(TIFF)而不是弄乱临时文件。
答案 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);