Вопрос

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

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

Для COM+ используется маршалинг Typelib, библиотека типов зарегистрирована, другие методы интерфейса работают нормально при вызове через 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+, содержимое буфера теряется.В частности, сохраняется только первый широкий символ - если сервер копирует строку широких символов «Образец», клиент получает только строку «S».Возвращаемое значение размера клиента — S_OK, длина буфера, возвращаемая клиенту, точно такая же, как и скопированная сервером.

В конце концов я переключился на BSTR, чтобы обойти эту проблему, но действительно интересно, почему вся правильно выглядящая конструкция не работает.

Какова возможная причина описанного поведения?

Это было полезно?

Решение

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

Другие советы

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

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

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

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

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

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

  • Почему ты не используешь BSTR?
  • Есть ли у вас исходники GetText функция?
  • Каков размер буфера, возвращаемого функцией?
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top