WCHAR数组未正确编组

时间:2009-05-13 11:47:07

标签: windows com interop marshalling

我有一个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来解决这个问题,但是为什么整个有效的结构不起作用真的很有趣。

所描述行为的可能原因是什么?

3 个答案:

答案 0 :(得分:3)

IIRC,typelib marshaller忽略了size_is属性 - 因此,只有1个字符被封送。

答案 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功能的来源?
  • 函数返回的缓冲区大小是多少?