Директива #import создала классы оболочки COM, заменяя wchar_t на unsigned short

У нас есть некоторый устаревший код, который использует MSXML и классы-оболочки, сгенерированные с использованием Visual Studio C ++ #import Директива такова:

#import <msxml6.dll> named_guids

Мы обновляем проект для использования wchar_t как встроенный тип (ранее /Zc:wchar_t- флаг был установлен, так wchar_t было unsigned short). Кажется, это вызывает проблемы, так как заголовки библиотеки типов генерируются с использованием #import замещать const wchar_t* входные параметры с unsigned short*,

Например, ISAXXMLReader::putProperty способ имеет следующее подпись:

HRESULT putProperty(
[in] const wchar_t * pwchName,
[in] VARIANT varValue);

но сгенерированный заголовок библиотеки типов использует следующую подпись:

HRESULT ISAXXMLReader::putProperty (
unsigned short * pwchName,
const _variant_t & varValue )

так не только wchar_t конвертировано в unsigned short, но const лишен. Таким образом, код не может быть скомпилирован без неприглядного приведения:

MSXML2::ISAXXMLReaderPtr saxReader(__uuidof(MSXML2::SAXXMLReader60));
MSXML2::IMXWriterPtr xmlWriter(__uuidof(MSXML2::MXXMLWriter60));

//Set properties on the XML writer.
// Omitted for brevity

saxReader->putProperty(L"http://xml.org/sax/properties/lexical-handler", // Can't convert to unsigned short*
(_variant_t)xmlWriter.GetInterfacePtr());

Есть ли способ получить директиву import для генерации правильных сигнатур функций в классах-оболочках?

редактировать Чтобы добавить к путанице msxml6.h заголовок объявляет класс C ++ ISAXXMLReader с ожидаемой подписью:

    virtual HRESULT STDMETHODCALLTYPE putProperty(
/* [in] */ const wchar_t *pwchName,
/* [in] */ VARIANT varValue) = 0;

хотя после прочтения предоставленного ответа, я думаю, он просто скрывает кровавые подробности. Но по крайней мере это согласуется с документацией (которая использует этот заголовок в своих примерах).

0

Решение

Комментарий Криса имеет хорошую ссылку, которая довольно четко описывает проблему. Подвести итоги:

Проблема в том, что подпись этого аргумента действительно является unsigned short * и не const wchar_t*Несмотря на то, что MSDN желает думать об обратном.

В некотором смысле, подпись в MSDN описывает моральное намерение параметра, а не его фактическую подпись.

Окончательным авторитетом для подписи является сама библиотека типов MSXML6. Как описывает ссылка в комментарии Криса, в библиотеке типов нет способа указать, что аргумент является «указателем на широкий символ», потому что автоматизация не поддерживает такую ​​вещь. Таким образом, они используют самую близкую вещь, которая совместима с ABI, и это unsigned short *,

#import Расширение компилятора может отражать только то, что находится в библиотеке типов. Нельзя сказать, чтобы он выборочно «лгал» в выводе.

Вот фактическая подпись этого метода, взятая прямо из библиотеки типов (через oleview.exe):

HRESULT _stdcall putProperty(
[in] unsigned short* pwchName,
[out, retval] VARIANT* pvarValue);

(У меня есть несколько рук, использующих oleview. В конце концов, вы смотрите на вывод генератора кода, как и в #import, так что он не доказывает ничего нового. Однако это лучшее, что мы можем обойтись без использования API библиотеки типов, чтобы самим посмотреть библиотеку типов).

Подобные вещи — это просто цена, которую вы платите за то, чтобы сделать ваш COM-объект доступным для клиентов автоматизации.

ДОПОЛНЕНИЕ:

Если вы посмотрите на интерфейс, вам будет интересно, как, черт возьми, вы можете позвонить тот из VB6 или VBScript. Что ж. ты не можешь

SAXXMLReader Coclass реализует два почти одинаковых интерфейса с одинаковой семантикой: ISAXXMLReader это интерфейс, на который мы смотрим, и это не удаленная, не автоматизированная, C ++ — оптимизированная версия интерфейса. Что вы получаете, когда вы используете SAXXMLReader объект из VB6 является его [default] интерфейс IVBSAXXMLReader, Это интерфейс, совместимый с автоматизацией наследования IDispatch, но он имеет ту же семантику, что и ISAXXMLReader, Для остроумия: IVBSAXXMLReader«s putProperty занимает BSTR вместо unsigned short *,

Документация MSDN для многих классов имеет тенденцию запутывать различие между тем, как объект вызывается из C ++ и VB / VBScript. Они создают видимость того, что вы вызываете одно и то же, но часто это не так, и скрывают детали интерфейса под ковриком. Я бы предпочел, чтобы они были немного более явными. Я предполагаю, что они должны в полной мере документировать семантику библиотеки, и должны обслуживать как нативных разработчиков, так и разработчиков сценариев, которые могут иметь совершенно разные уровни знаний в области сантехники COM.

2

Другие решения


По вопросам рекламы [email protected]