C ++, COM и передаваемые строки - PullRequest
0 голосов
/ 20 июля 2011

Я отлаживаю исходный код какого-то другого программиста плагина Windows Media Player.Этот плагин иногда вызывает сбой WMP, а иногда требуется очень много времени, чтобы открыть окно настроек плагина.Проблема возникает только при открытии окна настроек во время воспроизведения музыки.Он открывается без проблем, если проигрыватель остановлен.

Просматривая код и отлаживая, я пришел к строке кода, которая, кажется, является причиной проблем.

Свойствостраница имеет следующую переменную-член:

CComPtr<IDsp_plugin> m_pDsp_plugin;

и страница свойств при инициализации вызывает метод get_text COM-объекта:

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

В этот момент hres равно "0x80010105: сервер выбросилисключение."и выходные данные отладки Visual Studio показывают «Исключение первого шанса в 0x764efbae в wmplayer.exe: 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;
}

DLL-библиотека COM компилируется с параметром «Использовать набор символов Unicode».

Я не опытный программист COM, но передача строк в виде неподписанного символа ** мне кажется необычной, я видел в основном BSTR или VARIANT при работе с COM.

Может быть, некоторые гуру COM могутобъясните, почему это исключение происходит и может ли оно быть исправлено путем преобразования методов к использованию BSTR * и SysAllocString / SysfreeString вместо unsigned char ** / malloc / free?

1 Ответ

5 голосов
/ 20 июля 2011

Проще говоря, COM не знает, как передавать указатели типа unsigned char *.Применяются правила маршаллинга по умолчанию (поскольку в определении интерфейса не указаны атрибуты параметров), и, если я правильно интерпретирую это, COM правильно маршалирует внешний указатель txt, но обрабатывает *txt как указатель на single unsigned char, а не на строку.

Это может сработать, даже если звонящий и вызываемый абонент находятся в одной квартире;судя по всему, это не так.

Самое простое решение - просто сделать параметр BSTR *.COM имеет специальную обработку для BSTR, которая обеспечит его правильную передачу.

...