Reputation: 1108
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
Upvotes: 5
Views: 2794
Reputation: 30517
Here is my solution which uses macro and does not have boost dependency. You need to write below statement in your header file to declare << and >> operators.
For example:
DECLARE_ENUM_DATATYPE(QProcess::ProcessState)
and in one .cpp file add below statement to define << and >> operators.
CREATE_ENUM_DATATYPE(QProcess::ProcessState)
Both above functions require below file, you can save it as enumDBus.hpp
#ifndef _ENUM_DBUS_HPP
#define _ENUM_DBUS_HPP
#include <QtDBus/QDBusArgument>
#define DECLARE_ENUM_DATATYPE(ENUM_TYPE_DBUS)\
QDBusArgument &operator<<(QDBusArgument &argument, ENUM_TYPE_DBUS value);\
const QDBusArgument &operator>>(const QDBusArgument &argument, ENUM_TYPE_DBUS &val);
#define CREATE_ENUM_DATATYPE(ENUM_TYPE_DBUS)\
QDBusArgument &operator<<(QDBusArgument &argument, ENUM_TYPE_DBUS value)\
{\
argument.beginStructure();\
qlonglong newVal = (qlonglong)value;\
argument << newVal;\
argument.endStructure();\
return argument;\
}\
const QDBusArgument &operator>>(const QDBusArgument &argument, ENUM_TYPE_DBUS &val)\
{\
argument.beginStructure();\
qlonglong result = 0;\
argument >> result;\
val = (ENUM_TYPE_DBUS)result;\
argument.endStructure();\
return argument;\
}
#endif //_ENUM_DBUS_HPP
Upvotes: 1
Reputation: 1108
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>();
}
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
Upvotes: 4