遇到C4192警告时,我可以在#import指令中使用“exclude”吗?

时间:2013-08-07 05:44:33

标签: visual-studio-2008 com typelib

我有以下IDL:

import "oaidl.idl";
import "ocidl.idl";

[uuid(MyLibUuid), version(1.0)]
library MyLibrary
{
    importlib("stdole32.tlb");
    importlib("stdole2.tlb");
[object, uuid("MyInterfaceUuid"), nonextensible]
interface IMyInterface : IUnknown {
        HRESULT MyMethod( [in] IStream* stream );
    };
}

编译成.tlb文件并从另一个项目导入:

#import "PathToTypeLib.tlb" raw_interfaces_only

当编译它时,Visual Studio会发出以下输出:

warning C4192: automatically excluding 'IStream'
    while importing type library 'PathToTypeLib.tlb'
warning C4192: automatically excluding 'ISequentialStream'
    while importing type library 'PathToTypeLib.tlb'

好的,问题是因为那些importlib指令导致IStreamISequentialStream在类型库中定义 - MSDN explains it并说我必须使用includeno_auto_exclude#import

如果我使用no_auto_excludeinclude( "IStream", "ISequentialStream" )我现在有两个IStream定义 - 一个在全局命名空间中,另一个在typelib命名空间中,所以我的代码试图调用{{1} }不编译 - 编译器说

MyMethod

所以看起来我不得不使用error C2664: 'MyLibrary::MyInterface::MyMethod' : cannot convert parameter 1 from 'IStream *' to 'MyLibrary::IStream *' Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast - 这样它编译得很好并且看起来很有效。

使用exclude( "IStream", "ISequentialStream" )实际上是正确的解决方案吗?

1 个答案:

答案 0 :(得分:0)

如果IStream本身位于类型库上,例如您从IDL / TLB引用的stdole2.tlb,这将很有效。

不幸的是它不是,发生的是ID:编译器需要将你的IMyInterface放到库块上,并且自引用IStream以来,编译器也将它放到类型库中。因此,重复的声明会在您重新导入类型库时伤害到您。如果没有将自己的IStream接口放到类型库中,我认为你不能将它作为IStream

我使用的解决方法是避免在方法参数上使用IStream,而在其中使用IUnknown。如果/在适当的时候,调用者和被调用者会投射/ QI指针。通过这种方式,#import可以安全使用,并且可以正常运行。

[uuid(MyLibUuid), version(1.0)]
library MyLibrary
{
    importlib("stdole32.tlb");
    importlib("stdole2.tlb");
[object, uuid("MyInterfaceUuid"), nonextensible]
interface IMyInterface : IUnknown {
        HRESULT MyMethod( [in] IUnknown* pStreamUnkown ); // Instead of IStream
    };
}

呼叫者:

CComPtr<IStream> pStream;
pMyInterface->MyMethod(pStream);

被叫方:

STDMETHOD(MyMethod)(IUnkown* pStreamUnknown)
{
    CComQIPtr<IStream> pStream = pStreamUnknown;

Callee假设没有编组(最少开销):

STDMETHOD(MyMethod)(IUnkown* pStreamUnknown)
{
    ATLASSERT((IUnknown*) (IStream*) CComQIPtr<IStream>(pStreamUnknown) ==
      pStreamUnknown);
    const CComPtr<IStream>& pStream = 
      reinterpret_cast<const CComPtr<IStream>&>(pStreamUnknown);