Failing qobject_cast
-
[quote author="Franzk" date="1319726749"]
[quote author="rcari" date="1319722285"]I know this is a weird question but are you sure your model is not NULL in the first place ?[/quote]This is actually a good question.
[/quote]I don't think so since tallia1 calls model->metaObject(). If model == 0 the app would crash at this point, not later.
-
I just spent my morning trying to figure it out. Indeed rcari
is right, I didn't need to to qobject_cast. I was using it mostly
because I wanted to use introspection to see whether I was
doing something wrong...An important note is that the two classes are located in
different dynamically loaded libraries... so I am not sure
I can use the C++ dynamic_cast there...I will try what you suggest Volker.
-
-
And this is the output of this snippet:
@
const QMetaObject *mo = model->metaObject();
qDebug() << "Hierarchy: ";
while(mo) {
qDebug() << " " << mo->className();
mo = mo->superClass();
}
@Output:
@
Hierarchy:
SurfaceMeshModel
Model
QObject
MASSIVE FAIL.. TERMINATING
@ -
I am on OSX Lion. I isolated the problem even more. Look at the snippet below:
@
SurfaceMeshModel* model = new SurfaceMeshModel(path);Model* retval = qobject_cast<Model*>(model);
qDebug() << "Conversion Mesh=>Model: " << (retval?"success":"failed");SurfaceMeshModel* mesh = qobject_cast<SurfaceMeshModel*>(retval);
qDebug() << "Conversion Model=>Mesh: " << (mesh?"success":"failed");
@And the output is ...
@
Conversion Mesh=>Model: success
Conversion Model=>Mesh: failed
@ -
Weird. It's completely weird.
Just a another blind guess: may it be, that you happen to load two different versions of the Qt libs via the two libraries (resp. your app and library)? This may cause trouble too.
You can check this with the otool tool on the mac and some dyld debug settings:
@
export DYLD_PRINT_LIBRARIES=1
/path/to/your/Program.app/Contents/MacOS/Program 2>LOG-libraries.txt
unset DYLD_PRINT_LIBRARIES
@Then check LOG-libraries.txt for the loaded Qt libraries:
@
grep Qt LOG-libraries.txt
@It must not print libraries from different paths.
-
I think I am approaching the esoteric here :)
These two are defined in the same header that will compile into
the same library:
@
class LOCSurfaceMeshModel : public Model, public Surface_mesh{
Q_OBJECT
Q_INTERFACES(Model)
public:
LOCSurfaceMeshModel(){}
};class SurfaceMeshModel : public Model, public Surface_mesh{
Q_OBJECT
Q_INTERFACES(Model)
....
};
@Then this block is executed:
@
{
LOCSurfaceMeshModel* mod = new LOCSurfaceMeshModel();
Model* retval = qobject_cast<Model*>(mod);
qDebug() << "Conversion Mesh=>Model: " << (retval?"success":"failed");
LOCSurfaceMeshModel* mesh = qobject_cast<LOCSurfaceMeshModel*>(retval);
qDebug() << "Conversion Model=>Mesh: " << (mesh?"success":"failed");
}
{
SurfaceMeshModel* mod = new SurfaceMeshModel();
Model* retval = qobject_cast<Model*>(mod);
qDebug() << "Conversion Mesh=>Model: " << (retval?"success":"failed");
SurfaceMeshModel* mesh = qobject_cast<SurfaceMeshModel*>(retval);
qDebug() << "Conversion Model=>Mesh: " << (mesh?"success":"failed");
}
@And "OBVIOUSLY" the output is...
@
Conversion Mesh=>Model: success
Conversion Model=>Mesh: success
Conversion Mesh=>Model: success
Conversion Model=>Mesh: failed
@Complete NO-SENSE... Sigh.. I will go by elimination now..
I will strip down the original class to the one that work.. -
So by following the process above I found my error. It was this stray include lying in my runtime subsystem. (there was a time where I turned off the plugin system and did things locally)
@
#include "../lib_surfacemesh/SurfaceMeshModel.h" /// TO BE REMOVED
@I wish I could offer more intuition on WHY it was causing the whole dynamic casting to fail.. But I seriously have no clue!
NOTE: this fixed the cast/uncast ONLY when I was trying my test code. If an object is created from a plugin, casted to the interface object and casted back to the subclass in a second plugin... the cast still fails... triple sigh...
-
Let me use a small diagram to describe what is happening:
"Diagram":https://docs.google.com/drawings/d/1Jp-wpPuFTCvsC-3ovRmZXlRj93U0TfS7urxpfkLZPEc/editThe core runtime loads the plugins1/2
Everything else is statically linked to Core Runtime
Core runtime calls plugin1 to generate an instance of SurfaceMeshModel
(note: plugin1 casts this instance to the more general Model which is the only thing runtime knows about as the diagram shows)
Core runtime calls plugin2, which receives Model* and needs to cast it back down to SurfaceMeshModel <=== This is the failure point
What I mentioned above is that now the cast/uncast of an object within a single plugin works well. But if I create an object and pass it to another plugin... that's where the casting fails...
Do you see any fault with my design?
Andrea