2017-12-16 6 views
0

クラスをLPVOIDにキャストし、それをインターフェイスクラスに再キャストするときに問題があります。ここでは単純化されたコードは次のとおりです。インターフェイス参照の無効なキャスト例外

public interface class IEventRaiser 
{ 
    void fireAppDisconnect() 
    // some other methods 
} 

interface class ISpecificEventRaiser : IEventRaiser 
{ 
    // some specific methods 
} 

public ref class ManagedItem 
{ 
    ManagedItem() 
    { 
     eventRaiser = gcnew EventRaiser(); 
     LPVOID lP = reinterpret_cast<LPVOID>(GCHandle::ToIntPtr(GCHandle::Alloc(eventRaiser)).ToPointer(); 
     item = new UnmanagedItem(lP); 
    } 
    // some implementation 
    ref class EventRaiser : public ISpecificEventRaiser 
    { 
     virtual void fireAppDisconnect(); 
     // other methods 
    }; 

    EventRaiser^ eventRaiser; 
    UnmanagedItem* item; 
}; 

public class UnmanagedItem 
{ 
    UnmanagedItem(LPVOID eventRaiser) 
    { 
     IEventRaiser^ r; 
     IntPtr pointer(eventRaiser); 
     handle = GCHandle::FromIntPtr(pointer); 
     r = safe_cast<IEventRaiser^>(handle.Target); // InvalidCastException : Unable to cast object of type 'EventRaiser' to type 'IEventRaiser'. 
    } 
}; 

私は前にそれを試してみましたので、IEventRaiser ^へ^ EventRaiserにキャストすることには問題があってはなりません。会話をLPVOIDしようとする前に、うまくいきました。しかし、私はそれをLPVOIDにキャストし、それをIEventRaiserに再キャストすると、InvalidCastExceptionがスローされます。 LPVOIDでキャスティングを正しく行うにはどうすればいいですか?

+0

親愛なる@HansPassant、 それはアプリのライフタイムまで生き残り、私はデストラクタでhandle.free()を呼び出します。 IEventRaiserとして参照をラップしようとしましたが、同じ例外がスローされます。次のように。 ISpecificEventRaiser^sEventRaiser =(ISpecificEventRaiser ^)eventRaiser; lp = reinterpret_cast (GCHandle :: ToIntPtr(GCHandle :: Alloc(safe_cast (sEventRaiser)))。ToPointer(); –

+0

このコードスニペットを形にしてコンパイルするのは難しい作業です。私が試してみると、キャストは問題ではありません。間違いの可能性は、インターフェイスの種類の定義が複数あることです。これは、.hファイルで宣言して、それを#includeしたソースファイル.NETの型識別は、名前空間と識別子の名前だけではなく、アセンブリの完全な名前も含みます。代わりにアセンブリ参照を使用して、インタフェースの定義が1つしかありません。 –

+0

それを考えると、前にこの問題がすでに発生していました。あなたは[以前の質問](https://stackoverflow.com/q/47683677/17034)でまったく同じ間違いを犯しました。 –

答えて

0

アンマネージドクラスへのLPVOIDポインタを持つ理由は、ヘッダーの重複インポートを取り除くことでした。ですから、私はインクルードされたヘッダファイルに注意を払っていますが、IEventRaiserのヘッダファイルは、何らかの形で内在するプロジェクトにインポートされました。したがって、Hans Passantがコメントで示したように、アセンブリ名が異なるためにキャストの問題が発生します。私が問題を解決するためにしたのは、基本プロジェクトのIEventRaiserヘッダーファイルに#ifdefステートメントを追加することです。次のように:

#ifdef BASE_DLL 
#include "IEventRaiser.h" 
#endif 

次に、私は "BASE_DLL"にプリプロセッサ定義を追加しました。イベントライザーヘッダーが一度含まれることを保証します。もう1つの選択肢は、管理されていないファイルヘッダーに "IEventRaiser.h"ヘッダーファイルを追加しないようにするための前方宣言を使用することでした。それはまた試みられ、働いています。