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'

さて、問題は、タイプライブラリ内で発生および定義されたimportlibディレクティブへのものが原因であるためです-MSDNはそれを説明し、使用または使用する必要があると言います.IStreamISequentialStreamincludeno_auto_exclude#import

どちらno_auto_excludeかを使用するか、include( "IStream", "ISequentialStream" )現在2つのIStream定義があります.1つはグローバル名前空間にあり、もう1つは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

これは、IDL/TLB から参照するIStreamなど、それ自体がタイプ ライブラリ上にある場合にうまく機能します。stdole2.tlb

残念ながらそうではなく、何が起こるかというと、ID: コンパイラはあなたIMyInterfaceをライブラリ ブロックに配置する必要があり、IStream参照されるため、コンパイラはそれをタイプ ライブラリにも配置します。したがって、タイプ ライブラリをインポートし直すと、重複した宣言が問題になります。IStream独自のIStreamインターフェイスをタイプ ライブラリに取り込まずにそのまま使用することはできないと思います。

私が使用する回避策は、IStreamon メソッド パラメーターの使用を避け、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 に答える