参考自:
http://laurii.info/articles/2007/03/22/dbus-and-qt-programmin
http://blog.chinaunix.net/u2/69889/showart_2316513.html
根据第二个BLOG,我改动了部分代码,使用dbus interface调用方式,一步一步建立C/S结构代码:
[socol@localhost testdbus]$ ll
client
hotelibs
service
1. 建立库函数hotelibs
[socol@localhost testdbus]$ cd hotelibs
[socol@localhost hotelibs]$ ll
hotel.pro
hotel.cpp
hotel.h
[socol@localhost hotelibs]$cat hotel.h
#ifndef HOTEL_H #define HOTEL_H #include <QObject> #include <QReadWriteLock> #define MAX_ROOMS 10 class Hotel : public QObject { Q_OBJECT // 定义Interface名称为"com.test.hotel.registry" Q_CLASSINFO("D-Bus Interface", "com.test.hotel.registry") public: Hotel() { m_rooms = MAX_ROOMS; } public slots: // Check in,参数为房间数,返回成功拿到的房间数 int checkIn(int num_room); // Check out,参数为房间数,返回成功退回的房间数 int checkOut(int num_room); // Query,用于查询目前还剩下的房间数 int query(); private: int m_rooms; QReadWriteLock m_lock; }; #endif // HOTEL_H
[socol@localhost hotelibs]$cat hotel.cpp
#include <QtCore> #include <QtDBus> #include <QReadLocker> #include <QWriteLocker> #include "hotel.h" int Hotel::checkIn(int num_room) { QWriteLocker locker(&m_lock); if (m_rooms >= num_room) { m_rooms -= num_room; } else { num_room = m_rooms; m_rooms = 0; } return num_room; } int Hotel::checkOut(int num_room) { QWriteLocker locker(&m_lock); m_rooms += num_room; if (m_rooms > MAX_ROOMS) { num_room -= (m_rooms - MAX_ROOMS); m_rooms = MAX_ROOMS; } return num_room; } int Hotel::query() { QReadLocker locker(&m_lock); return m_rooms; }
[socol@localhost hotelibs]$ qdbuscpp2xml -A hotel.h -o com.test.hotel.xml
[socol@localhost hotelibs]$ qdbusxml2cpp com.test.hotel.xml -i hotel.h -p hotelInterface
[socol@localhost hotelibs]$ll
com.test.hotel.xml
hotel.cpp
hotel.h
hotelibs.pro
hotelInterface.cpp
hotelInterface.h
[socol@localhost hotelibs]$cat com.test.hotel.xml
<!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.test.hotel.registry"> <signal name="roomChanged"> <arg name="num_room" type="i" direction="out"/> </signal> <method name="checkIn"> <arg type="i" direction="out"/> <arg name="num_room" type="i" direction="in"/> </method> <method name="checkOut"> <arg type="i" direction="out"/> <arg name="num_room" type="i" direction="in"/> </method> <method name="query"> <arg type="i" direction="out"/> </method> </interface> </node>
[socol@localhost hotelibs]$cat hotelibs.pro
QT += dbus QT -= gui TARGET = hotelibs CONFIG += console CONFIG -= app_bundle TEMPLATE = lib SOURCES += hotelInterface.cpp hotel.cpp HEADERS += hotelInterface.h hotel.h
[socol@localhost hotelibs]$qmake-qt4 & make
[socol@localhost hotelibs]$sudo cp libhotelibs.so* /usr/lib
2. 建立服务端service
[socol@localhost testdbus]$ cd service
[socol@localhost service]$ ll
hotelservice.pro
main.cpp
[socol@localhost service]$cat hotelservice.pro
QT += dbus QT -= gui TARGET = hotelservice CONFIG += console CONFIG -= app_bundle TEMPLATE = app SOURCES += main.cpp LIBS += -L../hotelibs -lhotelibs INCLUDEPATH += ../hotelibs
[socol@localhost service]$cat main.cpp
#include <QtCore> #include <QtDBus> #include <QReadLocker> #include <QWriteLocker> #include "hotel.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); // 用于建立到session bus的连接 QDBusConnection bus = QDBusConnection::sessionBus(); // 在session bus上注册名为"com.test.hotel"的service if (!bus.registerService("com.test.hotel")) { qDebug() << bus.lastError().message(); exit(1); } Hotel my_hotel; #if 0 // adaport 方式,需要在hotelibs目录中运行: // qdbusxml2cpp com.test.hotel.xml -i hotel.h -a hotelAdaport new RegistryAdaptor(my_hotel); #else // 注册名为"/hotel/registry"的object。 // "QDBusConnection::ExportAllSlots "表示把类Hotel的所有Slot都导出为这个Object的method // 如果需要使用signal的话可以使用 QDBusConnection::ExportAllSignals bus.registerObject("/hotel/registry", &my_hotel, QDBusConnection::ExportAllSlots); #endif return a.exec(); }
[socol@localhost service]$qmake-qt4 & make
[socol@localhost service]$sudo cp hotelservice /usr/libexec/
[socol@localhost service]$sudo vim /usr/share/dbus-1/services/com.test.hotel.service
[socol@localhost service]$cat /usr/share/dbus-1/services/com.test.hotel.service
[D-BUS Service]
Name=com.test.hotel
Exec=/usr/libexec/hotelservice
3. 建立客户端client
[socol@localhost testdbus]$ cd client
[socol@localhost client]$ ll
main.cpp
hotelclient.pro
[socol@localhost client]$cat main.cpp
#include <QtCore> #include <QtDBus> #include <hotel.h> #include <hotelInterface.h> int main(int argc, char *argv[]) { int num_room; if (argc > 2) { fprintf(stderr, "Usage: %s [num_room]\n", argv[0]); exit(1); } if (argc == 2) { num_room = QString(argv[1]).toInt(); } else { num_room = 1; } // 初始化自动生成的Proxy类com::test::hotel::registry com::test::hotel::registry myHotel("com.test.hotel", "/hotel/registry", QDBusConnection::sessionBus()); // 调用checkIn QDBusPendingReply<int> reply = myHotel.checkIn(num_room); // qdbusxml2cpp生成的Proxy类是采用异步的方式来传递Message, // 所以在此需要调用waitForFinished来等到Message执行完成 reply.waitForFinished(); if (reply.isValid()) { num_room = reply.value(); printf("Got %d %s\n", num_room, (num_room > 1) ? "rooms" : "room"); } else { fprintf(stderr, "Check In fail!\n"); } return 0; }
[socol@localhost client]$cat hotelclient.pro
QT += dbus QT -= gui TARGET = hotelclient CONFIG += console CONFIG -= app_bundle TEMPLATE = app LIBS += -L../hotelibs -lhotelibs INCLUDEPATH += ../hotelibs SOURCES += main.cpp
4.测试
[socol@localhost client]$d-feet
// select query() execut, result 10
[socol@localhost client]$./hotelclient
Got 1 room
[socol@localhost client]$d-feet
// select query() execut, result 9