【发布时间】:2012-11-21 02:32:20
【问题描述】:
我试图破解 Qt 的信号和槽,我遇到了一个问题,即 QMetaType::invokeMethod 不能正确地将指针参数传递给被调用的槽。
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 *")
发生的情况是接收器上的插槽正在被调用,但无论我将什么传递给call(...) 作为Q_ARG,参数的值始终是0
出于好奇,我查看了接收器自动生成的 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] 的值具有MyObject * 的正确地址。但是reinterpret_cast 将其变成了0。
现在我有以下问题:
1) 如何以编程方式调用插槽并确保指针参数正确传递给插槽?
2) 这个*reinterpret_cast< MyObject*(*)>(_a[1]) 是什么意思?多余的括号(*) 是什么意思,如何解释这段代码?
【问题讨论】:
-
查看 SLOT() 宏。我已经有一段时间了,但这可能会回答你的问题。
-
invokeMethod允许您仅通过其名称和参数值调用插槽,而无需提供完整的签名。它工作正常,但不适用于非标准参数类型,至少对我来说...... -
这应该可以。您的 call() 实现似乎并未实际转发参数(或者这只是您的示例代码不正确?)。如果直接调用 QMetaObject::invokeMethod 可以吗? _a[1] 是指向指针的指针,因此 reinterpret_cast 中的 (*)。
-
是的,忘记重命名变量,将立即编辑。但回到
_a... 我认为_a[1]只是一个指针(因为_a是一个指向指针的指针)。为什么不直接写reinterpret_cast< MyObject *>(_a[1])?
标签: qt invoke reinterpret-cast metaobject