2017-12-16 1 views
0

클래스를 LPVOID로 캐스팅하고 인터페이스 클래스에 다시 캐스팅하는 데 문제가 있습니다. 여기에 간단한 코드입니다 : 내가 전에 그것을 시도하기 때문에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 파일에서 선언하고 # 소스 파일에 포함 할 때 발생하는 경향이 있습니다 NET에서 형식 ID는 네임 스페이스와 식별자 이름으로 정의되는 것이 아니라 함께 사는 어셈블리의 전체 이름도 포함합니다. 대신 인터페이스에 대한 정의가 하나만 있으므로 어셈블리 참조를 사용하십시오 –

+0

생각해 보니 이전에 이미이 문제가있었습니다. [이전 질문] (https://stackoverflow.com/q/47683677/17034)에서 똑같은 실수를하셨습니다. –

답변

0

내 관리되지 않는 클래스에 대한 LPVOID 포인터를 가져야하는 이유는 중복 헤더 가져 오기를 없애는 것이 었습니다. 그래서 헤더 파일에주의를 기울 였지만, IEventRaiser의 헤더 파일은 어떤 방식 으로든 inhereted 프로젝트로 임포트되었습니다. 따라서 한스 패전트 (Hans Passant)가 주석에 언급했듯이 어셈블리 이름이 다르기 때문에 캐스팅 문제가 발생합니다. 내가 문제를 해결하기 위해 수행 한 작업은 기본 프로젝트의 IEventRaiser 헤더 파일에 #ifdef 문을 추가하는 것입니다. 다음과 같이 :

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

그런 다음 전처리기 정의에 "BASE_DLL"을 추가했습니다. 이벤트 라이저 헤더가 한 번 포함되도록 보장합니다. 다른 대안은 "IEventRaiser.h"헤더 파일을 관리되지 않는 파일 헤더에 추가하지 않기 위해 포워드 선언을 사용하는 것이 었습니다. 그것은 또한 노력하고 노력하고 있습니다.