WCHAR 数组未正确编组
-
21-08-2019 - |
题
我有一个带有以下方法定义(IDL 表示法)的 COM 接口:
SCODE GetText( [in, out] ULONG* pcwcBuffer,
[out, size_is(*pcwcBuffer)] WCHAR* awcBuffer );
Typelib 封送处理用于 COM+,类型库已注册,通过 COM+ 调用时接口的其他方法可以正常工作,但此方法不行。
服务器端将 WCHAR 数组复制到 awcBuffer
及其长度为 pwcBuffer
, ,不会发生缓冲区溢出。
static const wchar_t* Text = L"Sample";
STDMETHODIMP CImpl::GetText( ULONG* bufferLength, WCHAR* buffer )
{
const int length = wcslen( Text );
*bufferLength = length;
memcpy( buffer, Text, length * sizeof( WCHAR ) );
return S_OK;
}
当客户端通过 COM+ 调用此方法时,缓冲区内容将丢失。具体来说,仅保留第一个宽字符 - 如果服务器复制“Sample”宽字符串,则客户端仅接收“S”字符串。客户端大小的返回值为S_OK,返回给客户端的缓冲区长度与服务器复制的完全相同。
我最终改用 BSTR 来解决这个问题,但真正有趣的是为什么整个看起来有效的构造不起作用。
所描述的行为的可能原因是什么?
解决方案
IIRC,类型库编组忽略size_is属性 - 因此,只有1炭封
。其他提示
学家传球是正确的。对于类型库编组工作,COM接口必须是OLE自动化兼容。该类型库编组中的oleaut32.dll实现的,所以我想有在名称中的线索。
[size_is]是完全有效的IDL,并且编译成一个有效的类型库,但类型库封送只能处理的有效接口的子集。该子集通常被称为OLE自动化。顺便说一句,VB6客户端只能说OLE自动化,所以他们将无法要么消耗你的界面。
尝试使用在IDL的[了oleautomation]属性标记的接口。它应该给你,可能指向你关于这个问题的更多信息,警告或错误信息。
在“正常”的COM,你可以生成从IDL代理/存根DLL做编组,但是我怕我不记得COM +是否会使用自定义编组代码,即使你不屑于建立它
更新:在朱瓦尔·洛书“COM和.NET组件服务”,我发现这样的说法:“ ...配置的组件不能使用需要自定义编组的接口”。所以我想这个接口将永远不会在COM +工作。如果可以的话,重新编写使用BSTR来代替。
有几个问题:
- 你为什么不使用
BSTR
? - 你有资源吗
GetText
功能? - 函数返回的缓冲区大小是多少?