我编写了一个C ++ COM服务器(进程外)和客户端,因此:
idl(接口为IDispatch
):
typedef[uuid(0952A366-20CC-4342-B590-2D8920D61613)]
struct MyStruct{
LONG id;
BYTE* data;
} MyStruct;
[helpstring("")] HRESULT foo([out] MyStruct* pStreamInfo);
服务器:
STDMETHODIMP foo(MyStruct* myStruct)
{
myStruct.id = 7;
myStruct.data = pData; // pData is a pointer to some data of variable length
return S_OK;
}
客户端:
MyStruct ms;
hr = comObj->foo(&ms);
除了添加myStruct.data = pData;
行会使服务器崩溃之外,该代码将正常工作。在客户端中分配内存ms.data = new BYTE[1000]
无济于事,因为指针仍然以foo
到达NULL
。
这将是一个解决方案,1.最好是最简单的客户端解决方案,因为接口将被各种用户使用。2.如果C#客户端使用接口,则解决方案是否会不同3.如果data
需要要脱离结构(我希望不是),这里有一个完整示例的引用。
答案 0 :(得分:0)
正如其他人在评论中提到的那样,您不能以这种方式传递原始数组。至少,您必须将字节数组复制到SAFEARRAY
个字节(在IDL中为SAFEARRAY(BYTE)
)。我只是使用自定义代理/存根(由midl.exe生成的P / S代码编译)测试了以下代码,并且能够通过网络获取数据。
如果您要使用标准的P / S,例如PSDispatch
({00020420-0000-0000-C000-000000000046}
)或PSOAInterface
({00020424-0000-0000-C000-000000000046}
),或者要将VBA用作客户端,则可能必须将其转换为SAFEARRAY(VARIANT)
和/或将生成的safearray放入VARIANT
。首先尝试仅使用SAFEARRAY(BYTE)
的最简单方法,因为那是开销最少的方法。 (SAFEARRAY(VARIANT)
使用的内存比SAFEARRAY(BYTE)
多16倍,因为VARIANT
的长度为16个字节。而且,您必须手动将每个字节与VARIANT
进行相互转换,如下所示:与下面显示的简单memcpy
调用相反。)
将字节数组包装到SAFEARRAY
中:(请注意,这会将字节数组复制到SAFEARRAY
中。您可以仔细研究{{1 }}的结构以防止复制,但是您将以非标准的方式进行操作。)
SAFEARRAY
从/// <summary>Packs an array of bytes into a SAFEARRAY.</summary>
/// <param name="count">The number of bytes.</param>
/// <param name="pData">A reference to the byte array. Not read if count is 0.</param>
/// <param name="pResult">Receives the packed LPSAFEARRAY on success.</param>
HRESULT PackBytes(ULONG count, const BYTE* pData, /*[ref]*/ LPSAFEARRAY* pResult)
{
// initialize output parameters
*pResult = NULL;
// describe the boundaries of the safearray (1 dimension of the specified length, starting at standard index 1)
SAFEARRAYBOUND bound{ count, 1 };
// create the safearray
LPSAFEARRAY safearray = SafeArrayCreate(VT_UI1, 1, &bound);
if (!safearray)
return E_OUTOFMEMORY;
// when there is actually data...
if (count > 0)
{
// begin accessing the safearray data
BYTE* safearrayData;
HRESULT hr = SafeArrayAccessData(safearray, reinterpret_cast<LPVOID*>(&safearrayData));
if (FAILED(hr))
{
SafeArrayDestroy(safearray);
return hr;
}
// copy the data into the safearray
memcpy(safearrayData, pData, count);
// finish accessing the safearray data
hr = SafeArrayUnaccessData(safearray);
if (FAILED(hr))
{
SafeArrayDestroy(safearray);
return hr;
}
}
// set output parameters
*pResult = safearray;
// success
return S_OK;
}
拆包字节数组:(请注意,这是从SAFEARRAY
复制字节数组。您可以仔细研究{{1 }}的结构可以防止复制,但是您将以非标准的方式进行操作,此外,您还可以通过将消耗代码放在SAFEARRAY
之间来选择直接从SAFEARRAY
使用数据和SAFEARRAY
。)
SafeArrayAccessData