#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 здесь весьма полезен.