#导入指令创建的COM包装类将wchar\u t替换为无符号短 我们有一些使用MSXML和使用VisualStudio的C++ >代码>导入/指令生成的包装类的遗留代码,如: #import <msxml6.dll> named_guids

#导入指令创建的COM包装类将wchar\u t替换为无符号短 我们有一些使用MSXML和使用VisualStudio的C++ >代码>导入/指令生成的包装类的遗留代码,如: #import <msxml6.dll> named_guids,c++,com,visual-studio-2013,msxml,C++,Com,Visual Studio 2013,Msxml,但生成的类型库标头使用以下签名: HRESULT ISAXXMLReader::putProperty ( unsigned short * pwchName, const _variant_t & varValue ) virtual HRESULT STDMETHODCALLTYPE putProperty( /* [in] */ const wchar_t *pwchName, /* [in] */ VARIANT v

但生成的类型库标头使用以下签名:

HRESULT ISAXXMLReader::putProperty ( 
    unsigned short * pwchName, 
    const _variant_t & varValue )
    virtual HRESULT STDMETHODCALLTYPE putProperty( 
        /* [in] */ const wchar_t *pwchName,
        /* [in] */ VARIANT varValue) = 0;
因此,不仅
wchar\u t
转换为
无符号短码
,而且常量被剥离。因此,如果没有难看的强制转换,代码无法编译:

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./Cuth>头,用期望签名声明:C++类<代码> iAxXMLReals< /C> >:

HRESULT ISAXXMLReader::putProperty ( 
    unsigned short * pwchName, 
    const _variant_t & varValue )
    virtual HRESULT STDMETHODCALLTYPE putProperty( 
        /* [in] */ const wchar_t *pwchName,
        /* [in] */ VARIANT varValue) = 0;

虽然在阅读了提供的答案后,我想这只是隐藏了血淋淋的细节。但至少它与文档(在其示例中使用此标题)一致。

Chris的评论有一个很好的链接,可以非常清晰地描述问题。总结如下:

问题在于,该参数的签名实际上是
unsigned short*
,而不是
const wchar\u t*
,尽管MSDN的一厢情愿正好相反

在某种程度上,MSDN中的签名描述了参数的道德意图,而不是其实际签名

签名的最终权威是MSXML6类型库本身。正如Chris评论中的链接所描述的,在类型库中没有办法表明参数是“指向宽字符的指针”,因为自动化不支持这样的事情。因此,他们使用最接近ABI兼容的东西,那就是
无符号短*

#import
编译器扩展只能反映类型库中的内容。没有办法告诉它在输出中有选择地“撒谎”

下面是该方法的实际签名,直接取自类型库(通过oleview.exe):

(我在使用oleview时遇到了很多麻烦。毕竟,您看到的是代码生成器的输出,就像#import一样,因此它并不能证明有什么新功能。但是,这是我们在不使用类型库API来查看类型库的情况下所能做的最好的事情)

这类事情正是您为使COM对象可供自动化客户端使用而付出的代价

增编:

如果您查看该接口,您必须想知道如何从VB6或VBScript调用。好。你不能

SAXXMLReader
coclass实现了两个语义相同的几乎成对的接口:
ISAXXMLReader
是我们正在研究的接口,它是该接口的非远程、非自动化、C++优化版本。使用VB6中的
SAXXMLReader
对象时得到的是它的
[默认值]
接口
IVBSAXMLReader
。这是一个IDispatch继承自动化兼容接口,但其语义与
isaxmlreader
相同。也就是说:
ivbsxxmlreader
putProperty
采用
BSTR
而不是
无符号短字符*


许多类的MSDN文档往往混淆了如何从C++和VB/VBScript中调用对象之间的区别。它们让你看起来像是在调用同一个东西,但通常情况并非如此,它们将接口细节隐藏在地毯下。我希望他们能更明确一点。我想他们必须在记录库的语义和满足本地开发人员和脚本开发人员的需求之间取得平衡,他们在COM的管道方面可能有着截然不同的专业水平

谷歌搜索“com import wchar\u t”给了我一条有用的线索:@ChrisJester Young是的,我找到了。我意识到我可以做一个演员,我想知道是否有办法避免它。假设是这样的话,有没有理由不写BSTR?(如果它是BSTR,那么编写
const wchar\u t*
是危险的,因为它表明函数需要一个以null结尾的宽字符串,这与BSTR不同。@MattMcNabb,它肯定不是BSTR,因为如果它是MS,则会将其定义为BSTR并完成。这是一个本机接口(不同于其近乎孪生的IVBSAXMLReader,它是一种纯自动化兼容的变体)。由于大多数人都会传递文本,因此他们对此进行了优化。实际上,传递BSTR应该是可以的(但您必须完全控制BSTR的内容!):您无论如何都不能封送该参数,它是“const”,并且语义上带有嵌入null的属性名无效,因此BSTR和wchar_t*之间的差异不应发挥作用。有
isaxmlreader
ivbsaxmlreader
。前者声明
无符号短*
(来自
wchar_t*
)后者是
BSTR
。前者不使用
[string]
MIDL属性,因此不能在公寓之间使用。我建议你如果有机会(即使是很小的机会)也坚持使用后者从另一个线程使用SAX读卡器,恢复到前一个线程。如果您没有从其他线程或iif中使用它,您会发现一个真正的性能瓶颈,并且您确信不会跨单元(即,所有使用它的线程都在MTA中).@euro还有一点不同:null bstr应该被视为空字符串,但是如果将null传递给wchar_t*函数,boom(10年前使用MSXML的第一手经验)@ChrisJester Young,你完全正确。当然。值得一提的是,空白命名属性在语义上也是无效的,因此它也不应该在这里起作用。(“你必须完全控制BSTR的内容!”)