Массив WCHAR неправильно распределен - PullRequest
0 голосов
/ 13 мая 2009

У меня есть интерфейс COM со следующим определением метода (нотация IDL):

SCODE GetText( [in, out] ULONG* pcwcBuffer,
              [out, size_is(*pcwcBuffer)] WCHAR* awcBuffer );

Маршалинг библиотеки типов используется для 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 ]

3 голосов
/ 13 мая 2009

IIRC, маршаллер typelib игнорирует атрибут size_is - таким образом, маршалируется только 1 символ.

2 голосов
/ 13 мая 2009

J. Проходить правильно. Чтобы маршаллер typelib работал, интерфейс COM должен быть совместим с OLE Automation. Маршаллер typelib реализован в oleaut32.dll, так что, думаю, в названии есть подсказка.

[size_is] является совершенно допустимым IDL и компилируется в действительную библиотеку типов, но маршалер библиотек типов может обрабатывать только подмножество допустимых интерфейсов. Это подмножество обычно называют OLE-автоматизацией. Кроме того, клиенты VB6 могут использовать только OLE-автоматизацию, поэтому они также не смогут использовать ваш интерфейс.

Попробуйте пометить ваш интерфейс атрибутом [oleautomation] в вашей IDL. Он должен дать вам предупреждение или сообщение об ошибке, которое может указать вам больше информации по теме.

В «обычном» COM вы можете сгенерировать прокси / заглушку DLL из вашей IDL для выполнения маршалинга, но я боюсь, что не помню, будет ли COM + использовать ваш собственный код маршаллинга, даже если вы не захотите его построить .

Обновление: в книге Ювала Лоуи "Службы компонентов COM и .NET" я нашел следующее утверждение: " ... настроенные компоненты не могут использовать интерфейсы, требующие пользовательского маршалинга ". Поэтому я думаю, что интерфейс никогда не будет работать в COM +. Если вы можете, переписать, чтобы использовать вместо него BSTR.

0 голосов
/ 13 мая 2009

Пара вопросов:

  • Почему вы не используете BSTR?
  • Есть ли у вас источники функции GetText?
  • Каков размер буфера, возвращаемого функцией?
...