2009-12-27 5 views
4

한다 : 나는 QT를 사용하고 있는데 QtPlugin와 (내 애플 리케이션을위한) 플러그인을 만들려고하고dynamic_cast는 NULL을 반환하지만 나는 다음과 같은 클래스 계층 구조에 봉착하지

class IStorage { 
    [...] 
} 
Q_DECLARE_INTERFACE(IStorage, "ch.gorrion.smssender.IStorage/1.0") 


class ISQLiteStorage: public IStorage { 
    Q_INTERFACES(IStorage) 

    [...] 
} 
Q_DECLARE_INTERFACE(ISQLiteStorage, "ch.gorrion.smssender.ISQLiteStorage/1.0") 


class DASQLiteStorage: public QObject, public ISQLiteStorage { 
    Q_OBJECT 
    Q_INTERFACES(ISQLiteStorage) 

    [...] 
} 

. 나는 DASQLiteStorage의 인스턴스를 만드는거야 내가 플러그인 내에서 직접 객체에이 인스턴스를 제공합니다 :

// the next line is within my main app. 
// storage is the DASQLiteStorage instance. 
// gateway is an object from within the plugin. 
gateway->setDefaultStorage(storage); 

// this method lies within the plugin 
void AbstractGateway::setDefaultStorage(IStorage* storage) { 
    defaultStorage_ = dynamic_cast<ISQLiteStorage*>(storage); 
} 

문제는 일을하면서 dynamic_cast는가, 나에게 널 포인터를 (예상되지 않음) 반환되어있다 내 메인 애플 리케이션 (즉, "게이트웨이 -> setDefaultStorage (스토리지);"전에 dynamic_cast) 내게 유효한 포인터 (예상)을 제공합니다.

왜 이런 일이 일어날 수 있는지 알고 있습니까? 프로그램이 플러그인과 다른 메모리 범위에서 작동합니까? 이러한 문제가 발생할 수 있습니까? 어떤 아이디어가 이것을 고치는 방법?

고맙습니다.


편집 : 내가 밖으로 시도했습니다 몇 가지 제안 : 방법의 첫 번째 줄에서

// this method lies within the plugin 
void AbstractGateway::setDefaultStorage(IStorage* storage) { 
    ISQLiteStorage* s = dynamic_cast<ISQLiteStorage*>(storage); 
    s = static_cast<ISQLiteStorage*>(storage); 
    s = qobject_cast<ISQLiteStorage*>((QObject*)storage); 

    defaultStorage_ = s; 
} 

, S는 두 번째의 올바른 포인터를 포함에, NULL과 동일 세 번째는 다른 포인터입니다. 이 포인터들이 왜 같지 않은가?
그리고 내가 지금 사용하고 있지만, 왜 dynamic_cast는 여전히 작동하지 않을 수 있습니다 :

pluginLoader()->setLoadHints(QLibrary::ResolveAllSymbolsHint | QLibrary::ExportExternalSymbolsHint); 




EDIT2 : 나는 눈치 , 분할 고장이 나는 코드에서 조금 더를 얻을이다 또한 이것과 관련있다. 다음과 같은 구조를 가지고 있습니다 :

// The following classes are defined within the main app. 
class ILoginAccount: public IAccount [...] 

class AbstractAccountStroageOfficer { 
public: 
    AbstractAccountStroageOfficer(IAccount* account)[...] 
} 


// These classes are defined within my plugin and are created from within the plugin. 
class BCAccount: public ILoginAccount { 
public: 
    BCAccount() 
     : ILoginAccount(new DAAccountStorageOfficer(this)) 
    {}; 
} 

class DAAccountStorageOfficer: public AbstractAccountStorageOfficer { 
public: 
    DAAccountStorageOfficer(ILoginAccount* account) 
     : AbstractAccountStorageOfficer(account) // This line raises a segfault. 
    { 
     IAccount* a = account; // This line raises a segfault as well. 
     a = dynamic_cast<IAccount*>(account); // This as well. 
     a = static_cast<IAccount*>(account); // This as well. 
    } 
} 

이러한 세분화 오류는 발생하지 않아야합니까? 그런데 왜 그런가요?

+0

응용 프로그램 내에'DASQLiteStorage' 클래스가 정의되어 있습니까? 계승 된 관계가 한쪽에만 알려진 경우 동적 하중 경계에서 어떤 일이 발생하는지 확신 할 수 없습니다. –

+0

IStorage는 이름 그대로 순수 가상 (즉, 인터페이스)입니까? 코드가'gateway-> setDefaultStorage (storage);에있을 때 'storage'의 타입은 무엇입니까? –

+0

DASQLiteStorage가 메인 어플리케이션에 정의되어 있습니다. 위의 설명에 썼 듯이 저장소 유형은 DASQLiteStorage입니다. –

답변

4

기본적으로 RTTI는 모듈 경계에서 신뢰할 수 없습니다. 다른 컴파일러는 여기에서 다른 동작을합니다. 이 경우 컴파일러/버전이 어떻게 작동하는지 연구해야합니다. 물론, 주 앱과 플러그인을위한 다른 컴파일러/버전을 가지고 있다면 분명히 작업 할 기회가 없습니다.

해결 방법으로 static_cast를 사용하십시오.

+0

static_cast를 실행하면 작동합니다. 하지만 코드에서 세분화 오류가 더 발생합니다.이것이 이것과 관련이 있다면 나는 모른다 ... 그래서 플러그인 환경의 dynamic_casting이 좋지 않으므로 피해야한다. –

+4

일반적으로 DLL과 Qt 클래스를 다룰 때는'dynamic_cast' 대신'qobject_cast'를 사용해야합니다. QtPlugin 문서에서도'qobject_cast'를 사용하여 플러그인이 특정 인터페이스를 구현하는지 확인해야합니다. –

+0

다중 상속이있는 상태에서 정적 캐스트를 사용하면 모든 종류의 문제가 발생할 것입니다. 런타임에 유형을 감지하고 적절한 변환을 수행 할 수 있어야합니다. –