5

私は次のクラス階層を持っています:

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)

    [...]
}

私は QT を使用しており、QtPlugin を使用して (自分のアプリ用に) プラグインを作成しようとしています。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 がヌル ポインターを返す (予期しない) ことですが、メイン アプリ内で (つまり、"gateway->setDefaultStorage(storage);" の前に) 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 に等しく、2 番目の s には正しいポインターが含まれ、3 番目には別のポインターが含まれます。これらのポインターが等しくないのはなぜですか?
そして、私が現在使用しているにもかかわらず、なぜ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.
    }
}

これらのセグメンテーション違反は発生すべきではありませんか? しかし、なぜ彼らはそうするのですか?

4

1 に答える 1

4

基本的に、RTTI はモジュールの境界を越えて信頼できません。ここでは、コンパイラが異なれば動作も異なります。この場合、コンパイラ/バージョンがどのように動作するかを調査する必要があります。もちろん、メイン アプリとプラグインのコンパイラ/バージョンが異なる場合、明らかに機能する可能性はありません。

回避策として static_cast を使用してください。

于 2009-12-27T00:33:37.807 に答える