3

我有以下 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'

好的,问题是因为那些在 typelib中importlib引起IStream和定义的指令 - MSDN 解释它并说我必须使用或使用.ISequentialStreamincludeno_auto_exclude#import

如果我使用其中一个,no_auto_exclude或者include( "IStream", "ISequentialStream" )我现在有两个IStream定义——一个在全局命名空间中,另一个在 typelib 命名空间中,所以我试图调用的代码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" )- 这样它编译得很好并且看起来工作。

是否使用exclude了正确的解决方案?

4

1 回答 1

0

如果IStream它本身位于类型库中,例如stdole2.tlb您从 IDL/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;

被调用者假设没有编组(开销最小):

STDMETHOD(MyMethod)(IUnkown* pStreamUnknown)
{
    ATLASSERT((IUnknown*) (IStream*) CComQIPtr<IStream>(pStreamUnknown) ==
      pStreamUnknown);
    const CComPtr<IStream>& pStream = 
      reinterpret_cast<const CComPtr<IStream>&>(pStreamUnknown);
于 2013-08-07T06:55:04.253 回答