Search code examples
c++qtenumsipcqtdbus

QtDBUS: Send Enums over DBUS


I'm using qt dbus binding in c++.

Currently I'm able to send any custom types (e.g.: class, structs) over dbus but I am not able to send an enumeration.

I also tried this link here, but I do not get it


Solution

  • I found a solution for my problem:

    First create a new header file called enums.h which looks like:

    #ifndef ENUMS_H
    #define ENUMS_H
    
    #include <QtDBus>
    #include "enumDBus.h"
    
    enum Color {
        RED = 0,
        BLUE,
        GREEN
    };
    
    Q_DECLARE_METATYPE(Color)
    
    #endif  /* ENUMS_H */
    

    Note following line #include "enumDBus.h", you can find this header file here.

    So after you declared the enum you can declare a method which takes the enum as argument, in this example I declared following method in calculator.h:

    void setColor(Color color);
    

    The implementation for this method:

    void Calculator::setColor(Color c)
    {
        switch (c) {
        case BLUE: std::cout << "Color: blue" << std::endl;
            break;
        case GREEN: std::cout << "Color: green" << std::endl;
            break;
        case RED: std::cout << "Color: reed" << std::endl;
            break;
        default:
            std::cout << "Color: FAIL!" << std::endl;
        }
    }
    

    Now let's generate the Interface description (XML), use following command

    qdbuscpp2xml -M -s calculator.h -o com.meJ.system.CalculatorInterface.xml
    

    The generation of method which contains custom types doesn't work properly, so we need to do some adjustments:

    <!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
    <node>
      <interface name="com.meJ.system.CalculatorInterface">
        <method name="setColor">
            <annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="Color"/>
            <arg type="(i)" direction="in" name="c"/>
        </method>
      </interface>
    </node>
    

    With this XML file we can simply create our adaptors and interfaces classes.

    In our main.cpp (on client and server!) we have to register our custom type:

    int main(int argc, char** argv)
    {
        qRegisterMetaType<Color>("Color");
        qDBusRegisterMetaType<Color>();
    }
    

    Client Side

    Include generated calculatorInterface.h and enums.h in your main.cpp.

    Now you can simply call your method:

    int main(int argc, char** argv)
    {
        qRegisterMetaType<Color>("Color");
        qDBusRegisterMetaType<Color>();
    
        QDBusConnection dbus = QDBusConnection::sessionBus();
    
        com::meJ::system::CalculatorInterface *calculator = new com::meJ::system::CalculatorInterface("com.meJ.system", "/Calc", dbus);
        if (calculator->isValid() == false) {
            cerr << "ERROR: " << qPrintable(calculator->lastError().message()) << endl;
            exit(1);
        }
    
        Color c = GREEN;
        calculator->setColor(c);
        std::cout << qPrintable(calculator->lastError().message()) << std::endl;
    
        exit(0);
    }
    

    If everything worked you should see following output at your server program:

    ~# Color: green