【问题标题】:C++, COM and passing stringsC++、COM 和传递字符串
【发布时间】:2011-10-08 21:43:41
【问题描述】:

我正在调试一些其他程序员的 Windows Media Player 插件源代码。这个插件有时会导致 WMP 崩溃,有时打开插件设置窗口需要很长时间。只有在播放音乐时打开设置窗口时才会出现此问题。如果播放器停止,它会毫无问题地打开。

在查看代码和调试时,我来到了似乎是问题原因所在的代码行。

属性页有如下成员变量:

CComPtr<IDsp_plugin> m_pDsp_plugin;

初始化时属性页调用COM对象的get_text方法:

unsigned char * txt = NULL;
//m_pDsp_plugin is a valid pointer to IDsp_plugin
HRESULT res = m_pDsp_plugin->get_text(&txt);

此时hrs是“0x80010105:服务器抛出异常”。并且 Visual Studio 调试输出显示“wmplayer.exe 中 0x764efbae 处的第一次机会异常:0x80010105:

get_text方法定义如下:

在 Dsp_plugin.idl 中

interface IDsp_plugin : IUnknown
{
    HRESULT get_text([out] unsigned char* *pVal);
...

在 Dsp_plugin.h 中

class ATL_NO_VTABLE CDsp_plugin : 
    public CComObjectRootEx<CComMultiThreadModel>,
    public CComCoClass<CDsp_plugin, &CLSID_Dsp_plugin>,
    public IDsp_plugin,
    public IMediaObject,
    public IWMPPluginEnable,
    public ISpecifyPropertyPages
{

    STDMETHOD(get_text)(unsigned char* *txt);
...

最后是抛出此异常的方法本身: dsp_plugin.cpp

STDMETHODIMP CDsp_plugin::get_text (unsigned char* *txt)
{
   ... // some code for copying a valid string from somewhere to char* y
   // 11 bytes of memory for y was allocated using malloc(10+1);
   // y contains a valid C string here, tested with debugger and passing to OutputDebugStringA

   *txt = (unsigned char*)(y); // This line executes normally, but at the end the caller gets "The server threw an exception." and WMP starts behaving weirdly. 
                               // If I comment it out, the caller gets S_OK and there are no any issues with WMP.

   return S_OK;
}

COM DLL 是通过设置“使用 Unicode 字符集”编译的。

我不是经验丰富的 COM 程序员,但将字符串作为 unsigned char** 传递对我来说似乎很不寻常,我在处理 COM 时主要看到 BSTR 或 VARIANT。

也许一些 COM 大师可以解释一下,为什么会发生这个异常,是否可以通过将方法转换为使用 BSTR* 和 SysAllocString/SysfreeString 而不是 unsigned char**/malloc/free 来修复它?

【问题讨论】:

    标签: c++ string exception com bstr


    【解决方案1】:

    简单地说,COM 不知道如何传递unsigned char * 类型的指针。应用了default marshalling rules(因为接口定义没有指定任何参数属性),并且,如果我正确解释这一点,COM 会正确编组外部指针本身txt,但将*txt 视为指向单个 unsigned char,而不是字符串。

    如果调用者和被调用者碰巧在同一个公寓里,这可能仍然有效;从它的声音来看,它们不是。

    最简单的解决方案是将参数设为BSTR *。 COM 对BSTR 有特殊处理,这将确保它被正确传递。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-11
      • 2011-09-09
      • 1970-01-01
      • 2014-09-23
      • 1970-01-01
      • 2012-11-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多