Qt - invoking slots that take custom pointers as arguments

2.9k Views Asked by At

I'm trying to hack with Qt's signals and slots, and I ran into an issue where QMetaType::invokeMethod won't properly pass pointer arguments to the slot being called.

call(QObject *receiver, const char *slot, const QList<QGenericArgument> &args)
{
    const QMetaObject *meta = receiver->metaObject();
    bool success = meta->invokeMethod(receiver, slot, 
            args.value(0, QGenericArgument()),
            args.value(1, QGenericArgument()),
            args.value(2, QGenericArgument()),
            ...
            args.value(9, QGenericArgument()));
}

Then I call it the following way:

MyReceiver *receiver;
MyObject *myObject;

call(receiver, "mySlot", QList<QGenericArgument>() << Q_ARG(MyObject *, myObject));

Where class MyObject : public QObject { ... }. I also do Q_DECLARE_METATYPE(MyObject *) and qRegisterMetaType<MyObject *>("MyObject *")

What happens is that the slot on the receiver is being invoked, but with the value of the argument is always 0 no matter what I pass to the call(...) as Q_ARG

Out of curiosity I looked into the auto-generated MOC file of the receiver, and found that the slots are invoked with the following code:

void MyReceiver::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
    if (_c == QMetaObject::InvokeMetaMethod) {
        Q_ASSERT(staticMetaObject.cast(_o));
        MyReceiver *_t = static_cast<MyReceiver *>(_o);
        switch (_id) {
        case 0: _t->mySlot((*reinterpret_cast< MyObject*(*)>(_a[1]))); break;
        default: ;
        }
    }
}

Turns out that the value of _a[1] bears proper address of MyObject *. But the reinterpret_cast turns it into 0.

Now I have the following questions:

1) How to programmatically invoke a slot and make sure that the pointer arguments are properly passed to the slot? 2) What does this *reinterpret_cast< MyObject*(*)>(_a[1]) mean? What the extra parentheses (*) mean, and how to interpret this piece of code?

1

There are 1 best solutions below

0
On

Ok, I think I figured why it's not working... Q_ARG only will create a pointer to my pointer and store the former. I didn't mention that the call function was part of the Task call meant to invoke a slot later on - when the values wrapped into Q_ARG are already out of scope. Basically Q_ARG only maintains a weak reference to the argument object.