我有以下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
指令导致IStream
和ISequentialStream
在类型库中定义 - MSDN explains it并说我必须使用include
或no_auto_exclude
与#import
。
如果我使用no_auto_exclude
或include( "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" )
实际上是正确的解决方案吗?
答案 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);