QMetaMethod из указателя на функцию-член

#c #qt

#c #qt

Вопрос:

Дан указатель на метод QObject производного класса: есть ли способ получить QMetaMethod метод, на который указывает указатель? Я в основном ищу функцию, подобную QMetaMethod::fromSignal , но для слотов.


Примечание: я попытался получить индекс через static_metacall с QMetaObject::IndexOfMethod помощью и использовать это для QMetaObject::method :

 void(Class::*method)() = amp;Class::method;
int methodIndex = -1;
void *metaArgs[] = {amp;methodIndex, reinterpret_cast<void **>(amp;method)};
const QMetaObject mo = Class::staticMetaObject;
mo.static_metacall(QMetaObject::IndexOfMethod, 0, metaArgs);
qDebug() << methodIndex;
// QMetaMethod mm = mo.method(methodIndex)
  

Результат всегда равен -1.

Комментарии:

1. Я не вижу никаких функций для выполнения того, что вы хотите. Рассмотрите возможность публикации вопроса о том, чего вы хотите достичь в более общем плане, чтобы посмотреть, существует ли другое решение. Часто лучше оставить метасистему Qt в покое, если только нет другого способа что-то сделать.

2. moc Сгенерированный код не реализует IndexOfMethod metacall для методов, не содержащих сигналов. Рассмотрите возможность отправки исправления в Qt. Смотрите qtbase/src/tools/moc/generator.cpp .

3. у вас очень странная потребность. Зачем вам нужно QMetaMethod из указателя в сигнал? Сигналы должны передаваться только от самого объекта, поэтому ваш случай очень странный и подозрительный.

4. @MarekR Мне не нужен QMetaMethod из указателя на сигнал (это было бы легко в любом случае, поскольку есть QMetaMethod::fromSignal ). Мне нужен QMetaMethod из указателя на слот. Я использую это для RPC. На данный момент я предоставляю моему методу RemoteCall строку с именем функции, которая должна быть вызвана. Использование указателя для получения QMetaMethod сделало бы его более элегантным и позволило бы проверять аргументы и возвращаемый тип во время компиляции.

5. Смотрите QTBUG-36861 , разработчики Qt, похоже, не хотят этого. Что именно вы хотите сделать с QMetaMethod ?

Ответ №1:

На данный момент единственным решением является изменение moc . Исправление довольно тривиально, хотя:

 diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp
index d831edf..7dcefcc 100644
--- a/src/tools/moc/generator.cpp
    b/src/tools/moc/generator.cpp
@@ -1311,15  1311,12 @@ void Generator::generateStaticMetacall()
             isUsed_a = true;
         }

-    }
-    if (!cdef->signalList.isEmpty()) {
-        Q_ASSERT(needElse); // if there is signal, there was method.
         fprintf(out, " else if (_c == QMetaObject::IndexOfMethod) {n");
         fprintf(out, "        int *result = reinterpret_cast<int *>(_a[0]);n");
         fprintf(out, "        void **func = reinterpret_cast<void **>(_a[1]);n");
         bool anythingUsed = false;
-        for (int methodindex = 0; methodindex < cdef->signalList.size();   methodindex) {
-            const FunctionDef amp;f = cdef->signalList.at(methodindex);
         for (int methodindex = 0; methodindex < methodList.size();   methodindex) {
             const FunctionDef amp;f = methodList.at(methodindex);
             if (f.wasCloned || !f.inPrivateClass.isEmpty() || f.isStatic)
                 continue;
             anythingUsed = true;
  

Затем следующее работает так, как ожидалось:

 // https://github.com/KubaO/stackoverflown/tree/master/questions/metamethod-lookup-24577095
#include <QtCore>

class MyObject : public QObject {
   Q_OBJECT
public:
   Q_SLOT void aSlot() {}
   Q_SLOT void aSlot2(int) {}
   Q_SLOT int aSlot3(int) { return 0; }
   Q_SIGNAL void aSignal();
   Q_SIGNAL void aSignal2(int);
};

template <typename Func> int indexOfMethod(Func method)
{
   using FuncType = QtPrivate::FunctionPointer<Func>;
   int methodIndex = -1;
   void *metaArgs[] = {amp;methodIndex, reinterpret_cast<void **>(amp;method)};
   auto mo = FuncType::Object::staticMetaObject;
   mo.static_metacall(QMetaObject::IndexOfMethod, 0, metaArgs);
   return methodIndex;
}

int main(int argc, char *argv[])
{
   QCoreApplication a(argc, argv);
   qDebug() << indexOfMethod(amp;MyObject::aSlot)
            << indexOfMethod(amp;MyObject::aSlot3) << indexOfMethod(amp;MyObject::aSignal2);
   return 0;
}
#include "main.moc"
  

Комментарии:

1. Вы отправили этот патч в Qt? Я спрашиваю, потому что иначе я мог бы. Или вы думаете, что это не очень хорошая идея включать это в общедоступную версию Qt?

2. Не стесняйтесь отправлять его. В данный момент у меня нет времени.

3. Поскольку Qt использует git, очень, очень просто установить кучу собственных исправлений поверх выпусков. Они просто перебазируются (переносятся вперед) каждый раз, когда вы переходите к другому тегу, и приходится исправлять случайные конфликты. git здесь весьма полезен.