1

なぜこれが起こっているのかわかりませんが、次のc#インターフェイスで定義できるc#関数の1つを実行すると:

[ComImport, Guid("EA5435EA-AA5C-455d-BF97-5F19DC9C29AD"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IClosedCaptionsDecoder2 
{
    [PreserveSig]
    int SetConfig([In] ref ClosedCaptionsDecoderConfig config);
    [PreserveSig]
    int GetConfig([Out] out ClosedCaptionsDecoderConfig config);
}

および C++ インターフェイス:

    interface __declspec(uuid("{EA5435EA-AA5C-455d-BF97-5F19DC9C29AD}"))
    IClosedCaptionsDecoder2 : public IClosedCaptionsDecoder
    {
        STDMETHOD(SetConfig)(IN CLOSEDCAPTIONSDECODERCONFIG& config) PURE;
        STDMETHOD(GetConfig)(OUT CLOSEDCAPTIONSDECODERCONFIG* pConfig) PURE;
    };

「以前の」インターフェースによって宣言された別の関数にリダイレクトされました。たとえば、次のコマンドを実行しようとすると: config->SetConfig(....)。関数 im がリダイレクトされる (または実行する次のコマンド) は、IClosedCaptionsDecoder2と呼ばれるIClosedCaptionsDecoder2の基本クラスによって実装されます。

このインターフェイスの C++ 宣言は次のとおりです。

interface __declspec(uuid("{26B8D7F1-7DD8-4a59-9663-8D00C03135F7}"))
        IClosedCaptionsDecoder : public IUnknown
        {
            STDMETHOD(xxx)(IExternalCCObserver* pObserver, LONG lFlags) PURE;
        };

そのため、config->SetConfig() は実際には config->xxx() を呼び出します。私の推測では、関数のオフフェストに何か問題があると思われます。

私はC#側(継承など)でリレーション全体を定義しようとしましたが、それもうまくいきませんでした。

助けていただければ幸いです。ありがとう!

編集: GetConfig() を呼び出そうとすると、実際に SetConfig() が実行されました。そのため、ポインターのオフセットなどに問題があることは間違いありません。各関数は、宣言順に前の関数を呼び出しますが、どうすれば可能ですか??

Edit2 : IClosedCaptionsDecoder2 インターフェイスにすべての機能を追加することで、このケースを解決できました。

4

1 に答える 1

1

これは、COM相互運用機能がCLRに実装される方法の欠陥の副作用です。インターフェイスがIUnknownまたはIDispatch以外の別のインターフェイスから派生している場合、インターフェイスのメソッドをv-tableスロットに適切にマップしません。具象コクラス実装で継承されたインターフェイスのメソッドによってすでに占有されている場合でも、最初のメソッドを最初に使用可能なスロットにマップします。多重継承をサポートしないことの副作用。したがって、問題は、クライアントコードがIClosedCaptionsDecoder :: xxx()を呼び出すと、代わりにIClosedCaptionsDecoder2 :: SetConfig()を呼び出すことになるということです。

回避策は簡単ですが、不快です。継承されたメソッドが含まれるように、インターフェイスをフラット化する必要があります。あなたの場合、それは次のようになります。

[ComImport, Guid("EA5435EA-AA5C-455d-BF97-5F19DC9C29AD"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IClosedCaptionsDecoder2 
{
    // Methods inherited from IClosedCaptionsDecoder:
    [PreserveSig]
    int xxx(whatever...);
    // Methods specific to IClosedCaptionsDecoder2
    [PreserveSig]
    int SetConfig([In] ref ClosedCaptionsDecoderConfig config);
    [PreserveSig]
    int GetConfig([Out] out ClosedCaptionsDecoderConfig config);
}

これは9月30日に米国で法律になり、これが機能するまであと6週間しかありません;)

于 2012-08-16T10:28:16.837 に答える