QDbus
API:QT 的帮助文档
任务描述:
proxy 获取 adaptor的数据,修改数据,接收数据修改的信号并查看新的值。
文件结构:
接口文件 XML:
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> <node name="/com/examples/qdbus/wtest"> <interface name="org.example.qdbus.wtest"> <signal name="valueChanged"> <arg name="newValue" type="d" direction="out"/> </signal> <method name="setValue"> <arg name="newValue" type="d" direction="in"/> </method> <method name="getValue" type="d" direction="out"/> </interface> </node>
依据XML生成源码的工具:qdbusxml2cpp
远端的函数返回值不能传递到client,但我们可以通过信号来传递server的value到client。
之所以能在server发送signal,让client作出响应,是因为WtestAdaptor和OrgExampleQdbusWtestInterface在构造函数中均有这样的设置: setAutoRelaySignals(true);
这样的话,可以在parent也就是server进程类中直接emit,进程间的信号转发就交给WtestAdaptor处理了。
// Adaptor/orgexampleddbustest_adaptor.h /* * Adaptor class for interface org.example.qdbus.wtest */ class WtestAdaptor: public QDBusAbstractAdaptor { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.example.qdbus.wtest") ... // Proxy/orgexampleddbustest_interface.h /* * Proxy class for interface org.example.qdbus.wtest */ class OrgExampleQdbusWtestInterface: public QDBusAbstractInterface { Q_OBJECT public: static inline const char *staticInterfaceName() { return "org.example.qdbus.wtest"; } ...
工程地址:https://github.com/theArcticOcean/qtLib/tree/master/DbusTest
GDbus
API:https://developer.gnome.org/gio/stable/gdbus-convenience.html
依据XML生成源码的工具:gdbus-codegen
还是使用QtDbus例子中的OrgExampleDdbusTest.xml。
然后,相关的文件DbusTest_code.h和DbusTest_code.c便生成了。
目录结构 (本工程使用waf工具进行编译):
DbusTest_code.h的部分内容:
struct _OrgExampleQdbusWtestIface { GTypeInterface parent_iface; gboolean (*handle_get_value) ( OrgExampleQdbusWtest *object, GDBusMethodInvocation *invocation); gboolean (*handle_set_value) ( OrgExampleQdbusWtest *object, GDBusMethodInvocation *invocation, gdouble arg_newValue); void (*value_changed) ( OrgExampleQdbusWtest *object, gdouble arg_newValue); }; //... /* D-Bus signal emissions functions: */ void org_example_qdbus_wtest_emit_value_changed ( OrgExampleQdbusWtest *object, gdouble arg_newValue); /* D-Bus method calls: */ void org_example_qdbus_wtest_call_set_value ( OrgExampleQdbusWtest *proxy, gdouble arg_newValue, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean org_example_qdbus_wtest_call_set_value_finish ( OrgExampleQdbusWtest *proxy, GAsyncResult *res, GError **error); gboolean org_example_qdbus_wtest_call_set_value_sync ( OrgExampleQdbusWtest *proxy, gdouble arg_newValue, GCancellable *cancellable, GError **error); //... OrgExampleQdbusWtest *org_example_qdbus_wtest_proxy_new_for_bus_sync ( GBusType bus_type, GDBusProxyFlags flags, const gchar *name, const gchar *object_path, GCancellable *cancellable, GError **error); //... OrgExampleQdbusWtest *org_example_qdbus_wtest_skeleton_new (void);
Client/GDbusClient.c 关键内容:
static gboolean onValueChanged ( OrgExampleQdbusWtest *object, double newValue, gpointer user_data ) { g_print( "onValueChanged, get value: %lf\n", newValue ); return TRUE; } int main( int argc, char *argv[] ) { //... proxy = org_example_qdbus_wtest_proxy_new_for_bus_sync( G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_NONE, "org.example.qdbus.wtest", "/com/examples/qdbus/wtest", NULL, &error ); if( NULL == proxy ) { g_print( "proxy init failed: %s", error->message ); exit( 0 ); } // connect step g_signal_connect( proxy, "value-changed", G_CALLBACK( onValueChanged ), NULL ); // set new value. org_example_qdbus_wtest_call_set_value_sync( proxy, 20, NULL, &error ); g_main_loop_run( loop ); // ... }
Server/GDbusServer.c 关键内容:
// Callback function on_handle_set_value has form // which is deined in struct _OrgExampleQdbusWtestIface static gboolean on_handle_set_value ( OrgExampleQdbusWtest *object, GDBusMethodInvocation *invocation, gdouble arg_newValue ) { g_print( "on_handle_set_value, set value: %lf\n", arg_newValue ); iPrivate.data = arg_newValue; org_example_qdbus_wtest_complete_set_value( object, invocation ); org_example_qdbus_wtest_emit_value_changed( object, arg_newValue ); return TRUE; } static void GBusAcquired_Callback ( GDBusConnection *connection, const gchar *name, gpointer user_data ) { GError *error = NULL; g_print( "GBusAcquired_Callback, name is %s, user_data: %s\n", name, (char *)user_data ); adaptor = org_example_qdbus_wtest_skeleton_new(); // connect step g_signal_connect( adaptor, "handle-set-value", G_CALLBACK( on_handle_set_value ), NULL ); g_dbus_interface_skeleton_export( G_DBUS_INTERFACE_SKELETON( adaptor ), connection, "/com/examples/qdbus/wtest", &error ); if( NULL != error ) { g_print( "Failed to export object: %s\n", error->message ); g_error_free( error ); } } //... int main() { GMainLoop* loop = NULL; guint own_id = g_bus_own_name( G_BUS_TYPE_SESSION, "org.example.qdbus.wtest", G_BUS_NAME_OWNER_FLAGS_NONE, GBusAcquired_Callback, GBusNameAcquired_Callback, GBusNameLost_Callback, NULL, NULL ); loop = g_main_loop_new( NULL, FALSE ); g_main_loop_run( loop ); g_bus_unown_name( own_id ); return 0; }
其中on_handle_set_value就是服务端的setValue函数,客户端调用org_example_qdbus_wtest_call_set_value_sync触发此函数的执行,在他设置新的value后也发送了信号通知客户端 org_example_qdbus_wtest_emit_value_changed
不知为啥,本工程在mac上总是连不上dbus,重启dbus守护进程也报错:
dbus-daemon --config-file=/usr/local/Cellar/dbus/1.12.8/share/dbus-1/session.conf --print-address dbus-daemon[34918]: Failed to start message bus: Check-in failed: No such process
然后,我就到Ubuntu上尝试了一波。可以的。
工程地址:https://github.com/theArcticOcean/CLib/tree/master/DbusTest