QMetaMethod :: invoke () с параметрами по умолчанию

При звонке 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 в качестве первого аргумента, то он работает нормально. Есть ли способ получить значения по умолчанию для аргументов метода, чтобы я мог передать их вместо ничего?

Я собирался вручную сохранить значения по умолчанию в классе для каждого метода, но это ужасный хак.

Спасибо за ваше время.

2

Решение

Если вы просмотрите сгенерированный файл .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;
5

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]