[Qt-interest] QMetaMethod invocation without compile-time knowledge of the return type
Thiago Macieira
thiago at kde.org
Thu Sep 24 09:47:10 CEST 2009
Em Quinta-feira 24. Setembro 2009, às 00.15.40, André Fillipe de Oliveira e
Silva escreveu:
> Introspector intro = getAnIntrospectorForMyObjectGraph();
> Author *author =
> intro.readProperty("rootObject.anotherObject.myObject.author[2]")
> .value<Author*>();
>
> and it will navigate from rootObject to myObject and return it's second
> author. All the path until "myObject" can be resolved using
> QObject::property(), but to resolve "myObject.author[2]" I will need to
> call, say, Author* MyObject::authorAt(int) using a QMetaMethod, to obtain
> the i-th author in the list of authors. The introspector, however, knows
> nothing about the Author class. It deals only with QObjects (Author, of
> course, extends QObject and Author* was registered with the Qt Metatype
> System).
Hi André
Actually, your introspector knows about QVariants too. That's your clue.
> My problem is: QMetaMethod::invoke has a QGenericReturnArgument parameter.
> QGenericReturnArgument is a template class, and one of it's parameters is
> the type of the return value. Therefore, I must know the type of the return
> value at compile time to properly construct a QGenericReturnArgument.
Hmm... you're confusing things.
QReturnArgument is a template class. QGenericReturnArgument isn't.
class Q_CORE_EXPORT QGenericReturnArgument: public QGenericArgument
{
public:
inline QGenericReturnArgument(const char *aName = 0, void *aData = 0)
: QGenericArgument(aName, aData)
{}
};
So you can do something like:
QVariant aux(qMetaTypeId<Author *>(), 0);
QGenericReturnArgument returnArg("Author*", aux.data());
QMetaObject::invokeMethod(obj, "authorAt", returnArg, Q_ARG(int, 2));
> But that only works for a direct access. One might want to chain indexed
> accesses (e.g. "myObject.author[2].book[3]") and the return types of the
> intermediate acessess must somehow be specified. An option:
Chained access will be very difficult. Once you make a call, you get an opaque
QVariant.
If all your return types are pointers to classes deriving primarily and non-
virtually from QObject, you can try something like this then:
QObject *pointer;
QGenericReturnArgument returnArg("Author*", &pointer);
QMetaObject::invokeMethod(obj, "authorAt", returnArg, Q_ARG(int, 2));
This is *technically* equivalent to the C++ code:
union { QObject *obj; Author *auth; } ptr;
ptr.auth = obj->authorAt(2);
use(ptr.obj);
It's not technically equivalent to:
QObject *obj2 = obj->authorAt(2);
use(obj2);
Please note the slight but important difference. When you assign an Author* to
a QObject*, the compiler will generate the necessary pointer adjustments so
that the QObject pointer points to the QObject sub-object inside the Author
object. If you use the union, then the pointers will have the same value, but
will not necessarily be correct.
I'm pointing this out to note that it isn't a generic solution. However, in
the case of classes that have a Q_OBJECT tag, moc will complain if the QObject
sub-object is not at offset zero. In other words, if you use Q_OBJECT, then the
trick above is safe.
> Why is it that QMetaMethod::invoke cannot accept a (non-const reference to
> a) QVariant and just proceed?
It can :-)
> Why is it necessary to provide the type name at compile time?
It's not.
It's not even necessary to provide the type name at all, if you call
qt_metacall directly. But please don't do that because in Qt 4.6 the semantics
of the meta call have changed slightly:
QVariant outArg; // initialised to QVariant(2) somewhere else
QObject *returnArg;
void *array[] = { &returnArg, const_cast<void*>(outArg.constData()) };
obj->qt_metacall(QMetaObject::InvokeMetaMethod, methodId, array);
use(returnArg);
See also:
http://qt.gitorious.org/qt/qt/blobs/master/src/dbus/qdbusintegrator.cpp#line808
and lines 869, 890
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Senior Product Manager - Nokia, Qt Development Frameworks
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
Qt Developer Days 2009 | Registration Now Open!
Munich, Germany: Oct 12 - 14 San Francisco, California: Nov 2 - 4
http://qt.nokia.com/qtdevdays2009
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 190 bytes
Desc: This is a digitally signed message part.
Url : http://lists.qt-project.org/pipermail/qt-interest-old/attachments/20090924/17e4b6df/attachment.bin
More information about the Qt-interest-old
mailing list