LINUX.ORG.RU

Вызов процедур по имени

 ,


0

3

Есть некий набор методов.
В ф-ию приходит переменная типа QString - имя_метода. Следущие переменный - параметры.
Нужно сделать вызов имя_метода, подставив ему эти аргументы.
Если метод не найден или аргументы не подходят по типу или количеству - кинуть исключение.
Как это сделать без case?
То-есть нужно сделать что-то вроде этого:

int func(QString _name, ...
{
    ...
    try{
    _name.execute(param1,param2....)
    }
}
Вопросы:
1.как передавать аргументы, а потом приводить их до нужного типа?
2. Как сделать _name.execute()?

★★★★

Последнее исправление: ymuv (всего исправлений: 2)

Сделать метод это слотом объекта и вызывать через инвок.
QMetaObject::invokeMethod(obj, slotName.toLatin1(), Qt::QueuedConnection, param1, param2, param3);

zJes ★★
()
Ответ на: комментарий от zJes

http://alenacpp.blogspot.com/2007/04/blog-post.html

Минусую

Сделать метод это слотом объекта и вызывать через инвок

Плюсую. Для Qt - самый верный путь. По дороге советую потыкать палкой в setProperty(...) и все что есть вокру. Зачастую упрощает жизнь.

trex6 ★★★★★
()
Ответ на: комментарий от zJes

Сделать метод это слотом объекта

Тогда уж не слотом, а просто Q_INVOKABLE.

Begemoth ★★★★★
()
Ответ на: комментарий от trex6

Begemoth trex6 zJes cdshines
а если на вход приходит конструкция виду:
(
QString «slot_name»,
(список параметров разных типов),
(возращаемый результат)
)
как ее лучше направить в

QMetaObject::invokeMethod(object, "slot_name", Qt::QueuedConnection, Q_ARG(type1, arg1), ...
если не извесно наперед какой тип будет?

ymuv ★★★★
() автор топика
Ответ на: комментарий от ymuv

если не извесно наперед какой тип будет?

Можно сделать функцию slot_name_wrapper(), которая будет принимать QVariant'ы на входе:

// Q_INVOKABLE slot_name_wrapper(const QVariant& arg1, const QVariant& arg2, const QVariant& arg3);

void myclass::slot_name_wrapper(const QVariant& arg1, const QVariant& arg2, const QVariant& arg3)
{
    slot_name(arg1.toInt(), arg2.toString(), arg3.toByteArray());
}

вызывать, соответственно, так:

QMetaObject::invokeMethod(
    object,
    "slot_name_wrapper",
    Qt::QueuedConnection,
    Q_ARG(QVariant, QVariant::fromValue(arg1),
    Q_ARG(QVariant, QVariant::fromValue(arg2),
    Q_ARG(QVariant, QVariant::fromValue(arg3)
);

А точно нужно Qt::QueuedConnection? Это будет асинхронный вызов.

sjinks ★★★
()
Ответ на: комментарий от sjinks

А если количество аргументов не известно как тогда?

не известно как тогда?

не известно наперед
к примеру:

void f1(int a){}
void f1(int a, int b){}
...

ymuv ★★★★
() автор топика
Последнее исправление: ymuv (всего исправлений: 4)
Ответ на: комментарий от ymuv

Передавай в метод ссылку на объект, в который запишешь результат.

trex6 ★★★★★
()
Ответ на: комментарий от ymuv

Это извращение :-)

У меня готового решения нет, но я бы попробовал сделать так:

const QMetaObject* meta = object->metaObject();
for (int i=meta->methodOffset(); i<meta->methodCount(); ++i) {
    QString signature = QString::fromLatin1(meta->method(i).signature());

/*
signature будет вида method(double,int)
Извлекаем метод, проверяем его на сопадение с переданным именем слота.
Если совпадают, проверяем количество аргументов (meta->method(i).parameterTypes().size()).
Если количество вариантов совпало, то создаём требуемое количество QGenericArgument:

*/
QGenericArgument args[10];
for (int j=0; j<meta->method(i).parameterTypes().size(); ++j) {
    args[j] = QGenericArgument(meta->method(i).parameterTypes().at(j), &(j-й параметр - я не знаю, как они передаются твоей функции));
    args.append(arg);
}

QMetaObject::invoke(object, method, Qt::QueuedConnection, args[0], args[1], ..., args[9]);
break;
}

Как-то так.

sjinks ★★★
()
Последнее исправление: sjinks (всего исправлений: 2)

Можно мне для общего развития, зачем это надо?

UVV ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.