我试图破解Qt的信号和插槽,并且遇到了QMetaType :: invokeMethod无法将指针参数正确传递到被调用的插槽的问题。Qt - 调用将自定义指针作为参数的插槽
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()));
}
然后,我把它叫做以下方式:
MyReceiver *receiver;
MyObject *myObject;
call(receiver, "mySlot", QList<QGenericArgument>() << Q_ARG(MyObject *, myObject));
哪里class MyObject : public QObject { ... }
。我也做Q_DECLARE_METATYPE(MyObject *)
和qRegisterMetaType<MyObject *>("MyObject *")
什么情况是,接收器上的插槽被调用,但随着参数的值总是0
不管我传递给call(...)
为Q_ARG
出于好奇我看着接收器的自动生成的MOC文件,发现槽用下面的代码调用:
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: ;
}
}
}
事实证明的_a[1]
值负有正确地址3210。但reinterpret_cast
将它变成0
。
现在我有以下问题:
1)如何以编程方式调用插槽,并确保该指针参数是否正确传递给插槽? 2)这个*reinterpret_cast< MyObject*(*)>(_a[1])
是什么意思?什么额外括号(*)
的意思,以及如何解释这段代码?
查看SLOT()宏。我对我来说有一段时间了,但这可能会回答你的问题。 – dmaij
'invokeMethod'允许您仅通过名称和参数值调用一个插槽,而不提供完整的签名。它工作正常,但不适用于非标准参数类型,至少对我来说... –
这应该工作。您的call()实现看起来并不实际地转发参数(或者这只是您的示例代码不正确?)。如果直接调用QMetaObject :: invokeMethod,它是否工作? _a [1]是一个指向指针的指针,因此reinterpret_cast中的(*)。 –