I cannot get methods from QMetaObject, offset and count methods are equal

I have a class that inherits from QObject and has a Q_OBJECT macro:

class SomeClass: public QObject { Q_OBJECT public: SomeClass(QObject *parent = 0); void method1(); void method2(); ... }; 

in another class in the same header, I create an instance of this class, and then I try to get all the methods from "SomeClass" and save it in QMap:

 this->someclass = new SomeClass(); // in constructor. 

...

 cout<<"init some class methods"<<endl; const QMetaObject *metaobj = dynamic_cast<QObject*>(this->someclass)->metaObject(); cout<<"offset "<<metaobj->methodOffset()<<endl; for(int i = metaobj->methodOffset();i < metaobj->methodCount();i++){ QMetaMethod metamethod = metaobj->method(i); //if(metamethod.methodType() == QMetaMethod::Method){ QString methodname = QString(metamethod.signature()); methodname = methodname.replace(QRegExp("\\(.*\\)"),""); controlmethods.insert(methodname,metamethod); cout<<"added method: "<<metamethod.signature()<<" as "<<methodname.toAscii().data()<<endl; //} } 

But this did not show me any method, because the offset of the methods is equal to the count method, why can this be? I do not understand the reasons, thanks to any help.

+4
source share
2 answers

You need to use the Q_INVOKABLE macro for each method that you want to see in QMetaObject .

From the documentation :

Q_INVOKABLE

Apply this macro to member function declarations so that they can be called through a meta-object system. A macro is written before the return type, as shown in the following example:

 class Window : public QWidget { Q_OBJECT public: Window(); void normalMethod(); Q_INVOKABLE void invokableMethod(); }; 

The invokableMethod () function is marked with Q_INVOKABLE, forcing it to register with the metaobject system and allowing it to be called with QMetaObject :: invokeMethod (). Since the normalMethod () function is not registered this way, it cannot be called with QMetaObject :: invokeMethod ().

You can also use the slots macro. I think Q_INVOKABLE might be more minimal.

QMetaObject only knows signals, slots, properties, and other calling member functions, sometimes called "meta methods" as a group.


Also, for the first line of your example, you should (probably) just call

 const QMetaObject *metaobj = someClass->metaObject(); 

This is not just cosmetics. dynamic_cast carry out type checking at runtime, which is not necessary if you know at compile time that someClass is a pointer to a QObject -derived class. ( dynamic_cast ing to QObject* will work, and you will get the correct QMetaObject due to virtual inheritance, but it is not needed, less secure and unclear.)

You really don't need an instance of the class to get the meta object:

 const QMetaObject *metaobj = SomeClass::staticMetaObject(); 

This is possible because there is one QMetaObject for each class, and not for each object.

For those who want to know more about the metaobject system, I recommend coffee and documentation . Normally, you do not need to directly access QMetaObject instances unless you are writing a script or something equally β€œmeta”. Easily inadvertently duplicating Qt functionality already provides.


Also, Q_DECLARE_METATYPE not what you want.

+5
source

There is some ambiguity in official documents .

First we see:

method () and methodCount () provide class information for meta-methods (signals, slots, and other invokable functions).

But later:

int QMetaObject :: methodCount () const Returns the number of methods in this class, including the number of properties provided by each base class. These include signals and slots, as well as a member of a normal function.

But in fact, we cannot access the β€œnormal” methods through the Qt MetaObject System.

So, in order to access your methods, you must declare them using the Q_INVOKABLE macro:

 Q_INVOKABLE void method1(); Q_INVOKABLE void method2(); 
+2
source

All Articles