我有一个COM接口,其中包含以下方法定义(IDL表示法):
SCODE GetText( [in, out] ULONG* pcwcBuffer,
[out, size_is(*pcwcBuffer)] WCHAR* awcBuffer );
Typelib marshaling用于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来解决这个问题,但是为什么整个有效的结构不起作用真的很有趣。
所描述行为的可能原因是什么?
答案 0 :(得分:3)
答案 1 :(得分:2)
学家传球是对的。要使typelib marshaller工作,COM接口必须与OLE Automation兼容。 typelib marshaller是在oleaut32.dll中实现的,所以我猜这个名字有一个线索。
[size_is]是完全有效的IDL,并且编译为有效的类型库,但是typelib封送器只能处理有效接口的子集。该子集通常称为OLE自动化。另外,VB6客户端只能说OLE自动化,因此它们也无法使用你的界面。
尝试使用IDL中的[oleautomation]属性标记您的界面。它应该给您一个警告或错误消息,可能会向您提供有关该主题的更多信息。
在“普通”COM中,您可以从IDL生成代理/存根DLL来进行编组,但是我担心我不记得COM +是否会使用您的自定义编组代码,即使您打算构建它也是如此
更新:在Juval Lowy的书“COM和.NET组件服务”中,我发现了这样的说法:“ ......配置的组件不能使用需要自定义编组的接口”。所以我猜这个界面永远不会在COM +中运行。如果可以,请重新编写以使用BSTR。
答案 2 :(得分:0)
几个问题:
BSTR
?GetText
功能的来源?