QMetaMethod::invoke() 带参数默认值
QMetaMethod::invoke() with argument defaults
在包含默认参数的方法上调用 QMetaMethod::invoke()
时,调用失败。
class MyClass : public QObject
{
Q_OBJECT
public:
Q_INVOKABLE MyClass() : QObject(nullptr){}
public slots:
int MyMethod(int a = 0)
{
return a*2;
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MyClass* object = new MyClass();
QMetaObject *metaObject = object->metaObject();
for(int i=metaObject->methodOffset(); i<metaObject->methodCount(); i++)
{
if(metaObject->method(i).name() == "MyMethod")
{
int returnVal;
//returns false
metaObject->method(i).invoke(object,
Qt::DirectConnection,
Q_RETURN_ARG(int, returnVal));
break;
}
}
return a.exec();
}
如果我将 int 作为第一个参数传递,那么它运行良好。有没有什么方法可以检索方法参数的默认值,这样我就可以传递这些参数而不是什么都不传递?
我正要手动将每个方法的默认值存储在 class 中,但这是一个丑陋的 hack。
感谢您的宝贵时间。
如果查看生成的 .moc,您会看到以下内容:
void MyClass::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
if (_c == QMetaObject::InvokeMetaMethod) {
MyClass *_t = static_cast<MyClass *>(_o);
Q_UNUSED(_t)
switch (_id) {
case 0: { int _r = _t->MyMethod((*reinterpret_cast< int(*)>(_a[1])));
if (_a[0]) *reinterpret_cast< int*>(_a[0]) = std::move(_r); } break;
case 1: { int _r = _t->MyMethod();
if (_a[0]) *reinterpret_cast< int*>(_a[0]) = std::move(_r); } break;
default: ;
}
}
}
如您所见,生成了 2 个方法,可以通过打印具有该名称的方法来验证:
#include <QCoreApplication>
#include <QMetaMethod>
#include <QDebug>
class MyClass: public QObject
{
Q_OBJECT
public:
using QObject::QObject;
public slots:
int MyMethod(int a = 0){ return a*2;}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MyClass object;
const QMetaObject *metaObject = object.metaObject();
for(int i=metaObject->methodOffset(); i<metaObject->methodCount(); i++)
{
QMetaMethod method = metaObject->method(i);
if(method.name() == QByteArray("MyMethod"))
qDebug()<<i<<method.name();
};
return 0;
}
#include "main.moc"
输出:
5 "MyMethod"
6 "MyMethod"
那么是什么让他们与众不同呢?参数个数,所以必须加一个过滤器,就是parameterCount()
.
#include <QCoreApplication>
#include <QMetaMethod>
#include <QDebug>
class MyClass: public QObject
{
Q_OBJECT
public:
using QObject::QObject;
public slots:
int MyMethod(int a = 0){ return a*2;}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MyClass object;
const QMetaObject *metaObject = object.metaObject();
for(int i=metaObject->methodOffset(); i<metaObject->methodCount(); i++)
{
QMetaMethod method = metaObject->method(i);
if(method.name() == QByteArray("MyMethod") && method.parameterCount() == 0)
{
int returnVal;
bool status = method.invoke(&object,
Qt::DirectConnection,
Q_RETURN_ARG(int, returnVal));
Q_ASSERT(status);
qDebug()<<returnVal;
}
};
return 0;
}
#include "main.moc"
输出:
0
另一方面,如果您想避免此类问题,您可以使用 QMetaObject::invokeMethod()
进行验证:
MyClass object;
int returnVal;
bool status = QMetaObject::invokeMethod(&object,
"MyMethod",
Qt::DirectConnection,
Q_RETURN_ARG(int, returnVal));
Q_ASSERT(status);
qDebug()<<returnVal;
在包含默认参数的方法上调用 QMetaMethod::invoke()
时,调用失败。
class MyClass : public QObject
{
Q_OBJECT
public:
Q_INVOKABLE MyClass() : QObject(nullptr){}
public slots:
int MyMethod(int a = 0)
{
return a*2;
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MyClass* object = new MyClass();
QMetaObject *metaObject = object->metaObject();
for(int i=metaObject->methodOffset(); i<metaObject->methodCount(); i++)
{
if(metaObject->method(i).name() == "MyMethod")
{
int returnVal;
//returns false
metaObject->method(i).invoke(object,
Qt::DirectConnection,
Q_RETURN_ARG(int, returnVal));
break;
}
}
return a.exec();
}
如果我将 int 作为第一个参数传递,那么它运行良好。有没有什么方法可以检索方法参数的默认值,这样我就可以传递这些参数而不是什么都不传递?
我正要手动将每个方法的默认值存储在 class 中,但这是一个丑陋的 hack。
感谢您的宝贵时间。
如果查看生成的 .moc,您会看到以下内容:
void MyClass::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
if (_c == QMetaObject::InvokeMetaMethod) {
MyClass *_t = static_cast<MyClass *>(_o);
Q_UNUSED(_t)
switch (_id) {
case 0: { int _r = _t->MyMethod((*reinterpret_cast< int(*)>(_a[1])));
if (_a[0]) *reinterpret_cast< int*>(_a[0]) = std::move(_r); } break;
case 1: { int _r = _t->MyMethod();
if (_a[0]) *reinterpret_cast< int*>(_a[0]) = std::move(_r); } break;
default: ;
}
}
}
如您所见,生成了 2 个方法,可以通过打印具有该名称的方法来验证:
#include <QCoreApplication>
#include <QMetaMethod>
#include <QDebug>
class MyClass: public QObject
{
Q_OBJECT
public:
using QObject::QObject;
public slots:
int MyMethod(int a = 0){ return a*2;}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MyClass object;
const QMetaObject *metaObject = object.metaObject();
for(int i=metaObject->methodOffset(); i<metaObject->methodCount(); i++)
{
QMetaMethod method = metaObject->method(i);
if(method.name() == QByteArray("MyMethod"))
qDebug()<<i<<method.name();
};
return 0;
}
#include "main.moc"
输出:
5 "MyMethod"
6 "MyMethod"
那么是什么让他们与众不同呢?参数个数,所以必须加一个过滤器,就是parameterCount()
.
#include <QCoreApplication>
#include <QMetaMethod>
#include <QDebug>
class MyClass: public QObject
{
Q_OBJECT
public:
using QObject::QObject;
public slots:
int MyMethod(int a = 0){ return a*2;}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MyClass object;
const QMetaObject *metaObject = object.metaObject();
for(int i=metaObject->methodOffset(); i<metaObject->methodCount(); i++)
{
QMetaMethod method = metaObject->method(i);
if(method.name() == QByteArray("MyMethod") && method.parameterCount() == 0)
{
int returnVal;
bool status = method.invoke(&object,
Qt::DirectConnection,
Q_RETURN_ARG(int, returnVal));
Q_ASSERT(status);
qDebug()<<returnVal;
}
};
return 0;
}
#include "main.moc"
输出:
0
另一方面,如果您想避免此类问题,您可以使用 QMetaObject::invokeMethod()
进行验证:
MyClass object;
int returnVal;
bool status = QMetaObject::invokeMethod(&object,
"MyMethod",
Qt::DirectConnection,
Q_RETURN_ARG(int, returnVal));
Q_ASSERT(status);
qDebug()<<returnVal;