Массив WCHAR не упорядочен должным образом.
-
21-08-2019 - |
Вопрос
У меня есть 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
функция? - Каков размер буфера, возвращаемого функцией?