Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How to use a macro function as a Qt slot



  • Hi all,

    I am trying to define some slots which will be expanded from a macro. I can achieve this if the macro definition is within the same file as the macro usage. However, if the macro definition and the usage is in different file, I am getting parsing error from the moc tool - ***Parse error at ")"***.

    Qt version used: 5.4.1

    I have provided some example below. Thanks in advance for the help.

    Working Example:

    foo.h

    public slots:
    #define SOME_FUNC(func, var) \
        void func##var()         \
        {                        \
            TestFunc(); // Assume this function is defined in this class         \
        }                        \
    
       SOME_FUNC(DoFunc, 1);
       SOME_FUNC(DoFunc, 2);
    

    Non-working example
    fooDef.h

    #define SOME_FUNC(func, var) \
        void func##var()         \
        {                        \
            TestFunc();// Assume this function is defined in the user class    \
        }                        \
    

    foo.h

    #include "fooDef.h"
    
    Class MyClass : public QObject
    {
        Q_OBJECT
    
    // Other definitions
    
    public slots:
       SOME_FUNC(DoFunc, 1);
       SOME_FUNC(DoFunc, 2);
    


  • @Sivan

    This is certainly an advanced topic. Gut feeling tells me that there are at least a number of obstacles and most likely it is not possible.

    One reason is that the older style of connect statements are using already macros to do the connect. Therefore you would need a multi-level macro support.

    Possibly with the functor-based connect you can have a similar feature as you try to do with macros.

    Probably best is to describe a bit more what you try to achieve with your macros. I personally would favor any other solution, but macros.


  • Moderators

    I is quite likely that MOC parser just isn't clever enough to pick up a macro defined elsewhere.



  • Thanks @koahnig & @sierdzio. I was afraid it is not possible too. But just wanted to try my luck if there is anyway in achieving it.

    @koahnig, the reason for me to do that is abit complex to be explained here as I am trying to make thing works in an existing framework.
    My requirement was that I may have a list of Q_SLOT functions with the following signature format myFuncXXX(), where XXX will vary.

    Eventually, all this functions will call one private function by passing in the appropriate enum or something. I can't directly do it due to the existing framework which will try to find the list of moc generated functions with the above mentioned signature. And the reason to put the macro in one file is to allow many other classes/files to reuse those macros rather than copying it definition in each file.

    But anyways, looks like I am constrained by the current design. Thanks for answering :-)



  • @Sivan said in How to use a macro function as a Qt slot:

    But anyways, looks like I am constrained by the current design

    I think it's totally possible, just don't declare them as slots, declare them as public methods (so moc doesn't have to meddle with them) and use Qt5 Connection Sintax



  • @VRonin, sorry if I missed this. I believe that will still not work for my case.

    Because the framework loop through the QObject::metaObject->method of QObject to find these functions that I have defined. So if I do not define it under the Slots section, then I don't think so it will come under QObject::metaObject->method


  • Moderators

    You can define them with Q_INVOKABLE, then.

    Hm, unless that will trigger the same MOC error...



  • @sierdzio, that kinda gave me hope. But it is still not working :-(

    I moved the MACRO usage to public instead of public slots, and added Q_INVOKABLE in front of the function as like this

    Q_INVOKABLE void func##var()
    

    No luck - None of those MACRO functions were registered under Meta Object. I verified by looping through MetaObject->method() to find those functions.

    However, the moc does not give any error. It just silently ignore. I guess that's because it ignores unsuccessful MACRO parsing that is not under the signal and slot sections


  • Moderators

    @Sivan as you've discovered, moc doesn't work very well with custom macros. This is because moc uses simple string parsing, so when it sees Q_INVOKABLE void func##var() it thinks the function is literally called func##var().

    For now, all slots must be explicitly written. This could change in the future if/when moc-ng (https://woboq.com/blog/moc-with-clang.html ) is integrated with Qt, but that's still a while away.



  • This is probably a long shot but if you really want this you could try a moc-less solution: https://woboq.com/blog/verdigris-qt-without-moc.html



  • Thanks @JKSH and @VRonin for the input. As of now, I have settled down by explicitly writing the macros.


Log in to reply