views:

502

answers:

2

Hi

I'm having the following class hierarchy:

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)

    [...]
}

I'm using QT and am trying to create a plugin (for my app) with QtPlugin. I'm creating an instance of DASQLiteStorage and I give this instance to an object FROM WITHIN the plugin:

// 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);
}

The problem is, that the dynamic_cast is returning me a null-pointer (not expected), while doing the dynamic_cast within my main app (i.e. before "gateway->setDefaultStorage(storage);") gives me the valid pointer (expected).

Does anyone know why this could happen? Is the program operating in a different memory range as the plugin? Could this lead to such problems? Any ideas how to fix this?

Thanks a lot!


EDIT: I've tried out some suggestions:

// 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;
}

In the first line of the method, s equals NULL, in the second s contains the correct pointer and in the third an other pointer. Why aren't these pointers equal?
And why could the dynamic_cast be still not working although I'm using now:

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




EDIT2: I noticed, that the segmentation fault I get a little further in the code is also related to this. I have the following construct:

// 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.
    }
}

These segmentation faults should not occur, should they? But why do they?

+2  A: 

Basically, RTTI is unreliable across module boundaries. Different compilers have different behaviors here; you'll have to research how your compiler/version acts in this case. Of course, if you have a different compiler/version for the main app and plugin, it clearly has no chance of working.

Use static_cast as a work around.

Terry Mahaffey
When I do a static_cast, it works. But I get a segmentation fault further in the code. I don't know, if this is relatet to this...So, is dynamic_casting in plugin environments bad and should be avoided?
Sämy
In general, when dealing with DLLs and Qt classes, you should use `qobject_cast` instead of `dynamic_cast`. Even in the QtPlugin docs you can find that you should use `qobject_cast` to determine whether a plugin implements a specific interface.
Lukáš Lalinský
Using static cast in the presence of multiple inheritance is going to cause all sorts of problems. You need to be able to detect the type at runtime and do the appropriate translation.
Martin York
Not true; static_cast handles multiple inheritance fine (it does pointer adjustment). You're thinking of reinterpret_cast - which doesn't do pointer adjustments.
Terry Mahaffey
Please see my edit in my original post...
Sämy
+1  A: 

See the answer to this question, I believe that I had a similar issue and eventually solved it:

http://stackoverflow.com/questions/441983/dynamic-cast-with-interfaces

Evan Teran