基于GDbus与QDbus的DBUS小练习

匿名 (未验证) 提交于 2019-12-03 00:29:01

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
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!