02.26 gdbus demo程序簡介


近期想要寫一個gdbus的demo程序,查閱了一下資料,發現貌似gdbus之間的IPC通信分為兩種,一種是基於system總線,一種是基於session,我通過session通信的方式簡單寫了一個p2p的demo程序。首先通過gdbus-codegen 生成.h 和.c 文件,然後通過glib gio的接口分別寫了一個客戶端和服務端,客戶端通過method與服務端進行同步通信,服務端通過signal 主動向客戶端發送信號通知。服務端流程圖如下

gdbus demo程序簡介

客戶端流程圖如下

gdbus demo程序簡介


程序使用automake進行構建,結構如下

<code>├── autogen.sh├── configure.ac├── LICENSE├── Makefile.am├── private-include│ ├── common.h│ ├── gdbus_client.h│ └── gdbus_server.h├── README.md└── src├── Building.xml├── gdbus_client.c├── gdbus_server.c└── Makefile.am/<code>


下面把各文件的內容貼上

1. Building.xml

<code><node><interface><method>/<method><signal>/<signal>/<interface>/<node>/<code>

method中s代表字符串,i代表數字,其中direction中in代表入參,即發送的值,out代表出參,即獲取的值signal代表服務端發送的信號,此處表示發送一個數字

2. Makefile.am

<code>AM_CFLAGS = $(GLIB_CFLAGS) $(GIO_CFLAGS) -gAM_CPPFLAGS = -I$(top_srcdir)/private-includeBUILT_SOURCES = Building.c Building.hdist_noinst_DATA = Building.xmlbin_PROGRAMS = gdbus_server gdbus_clientgdbus_server_SOURCES = gdbus_server.c \\Building.c Building.hgdbus_server_LDADD = $(GLIB_LIBS) $(GIO_LIBS)gdbus_client_SOURCES = gdbus_client.c \\BuildingClient.c BuildingClient.hgdbus_client_LDADD = $(GLIB_LIBS) $(GIO_LIBS)Building.c Building.h : Building.xmlgdbus-codegen  --interface-prefix=com.qiaotsh.Building --generate-c-code=Building $<mostlycleanfiles>/<code>

Makefile.am中使用gdbus-codegen對Building.xml進行處理,生成Building.h Building.c,

–interface-prefix代表省略前綴名com.qiaotsh.Building,這樣在生成文件中將以Test為函數開頭,否則字符串看起來比較冗餘,是comqiaoBuildingtest開頭,目的是增強可讀性,–generate-c-code代表生成C語言代碼

3. gdbus_client.c

<code>/** =====================================================================================**       Filename:  gdbus_client.c**    Description:**        Version:  1.0*        Created:  02/17/2017 08:28:34 AM*       Revision:  none*       Compiler:  gcc**         Author:  qiaotsh (), [email protected]*   Organization:  www.neusoft.com** =====================================================================================*/#include <glib.h>#include  
#include <unistd.h>#include "Building.h"#include "gdbus_client.h"static gboolean test_status_handler(Test* object,gint status,gpointer user_data){g_print("signal received %d\\n",status);return TRUE;}static void cb_OwnerNameChangedNotify(GObject *object, GParamSpec *pspec, gpointer userdata){gchar *pname_owner = NULL;pname_owner = g_dbus_proxy_get_name_owner((GDBusProxy*)object);if (NULL != pname_owner){g_print("DBus service is ready!\\n");g_free(pname_owner);}else{g_print("DBus service is NOT ready!\\n");g_free(pname_owner);}}int main(int argc, char *argv[]){Test *proxy=NULL;GError *error = NULL;GMainLoop* loop = NULL;proxy = test_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,G_DBUS_PROXY_FLAGS_NONE,"com.qiaotsh.Building.Test","/com/qiaotsh/Building/Test",NULL,&error);if(0 == proxy){g_print("InitDBusCommunication: Failed to create proxy. Reason: %s.\\n", error->message);}g_signal_connect(proxy,"test-status",G_CALLBACK(test_status_handler),NULL);char *reply = NULL;test_call_set_version_sync (proxy, "hello world", &reply,NULL, &error);g_print("sync reply = %s\\n",reply);loop = g_main_loop_new(NULL, FALSE);g_main_loop_run(loop);g_object_unref(proxy);return 0;}/<unistd.h>/<glib.h>/<code>

值得注意的是test_status_handler的參數不是隨便定義的,具體形式在Building.c中有詳細描述

4. gdbus_server.c

<code>/** =====================================================================================**       Filename:  gdbus_client.c**    Description:**        Version:  1.0*        Created:  02/17/2017 08:28:34 AM*       Revision:  none*       Compiler:  gcc**         Author:  qiaotsh (), [email protected]*   Organization:  www.neusoft.com** =====================================================================================*/#include<stdio.h>#include#include<glib.h>#include<assert.h>#include"Building.h"#include"gdbus_server.h"static Test* skeleton=NULL;static gboolean Emit_Test_Status(gconstpointer p){g_print("Emit_Test_Status() is called.\\n");gint status = 5;test_emit_test_status (skeleton,status);return TRUE;}static  gboolean on_handle_set_version(Test* skeleton,GDBusMethodInvocation *invocation,const gchar *greeting,gpointer user_data){g_print("Method call: %s\\n", greeting);char* reply = "getSuccess";test_complete_set_version (skeleton,invocation,reply);return TRUE;}void GBusAcquired_Callback (GDBusConnection *connection,const gchar *name,gpointer user_data){GError *error = NULL;printf("GBusAcquired_Callback has been invoked\\n");printf("GBusAcquired_Callback the name = %s\\n",name);printf("GBusAcquired_Callback the user_data = %s\\n",(char*)user_data);skeleton =  test_skeleton_new ();g_signal_connect(skeleton,"handle-set-version",G_CALLBACK(on_handle_set_version),NULL);g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(skeleton), connection, "/com/qiaotsh/Building/Test", &error);if(error != NULL){g_print("Error: Failed to export object. Reason: %s.\\n", error->message);g_error_free(error);}}void GBusNameAcquired_Callback (GDBusConnection *connection,const gchar *name,gpointer user_data){printf("GBusNameAcquired_Callback has been invoked\\n");}void GBusNameLost_Callback (GDBusConnection *connection,const gchar *name,gpointer user_data){printf("GBusNameLost_Callback has been invoked\\n");}int main(int argc,char* argv[]){char* s = "qiaotsh";GMainLoop* loop = NULL;guint own_id =g_bus_own_name (G_BUS_TYPE_SESSION,"com.qiaotsh.Building.Test",G_BUS_NAME_OWNER_FLAGS_NONE,GBusAcquired_Callback,GBusNameAcquired_Callback,GBusNameLost_Callback,(gpointer)s,NULL);/* * emit my signal1 every 1 second to trigger example communication */g_timeout_add(1000, (GSourceFunc)Emit_Test_Status, NULL);loop = g_main_loop_new(NULL, FALSE);g_main_loop_run(loop);g_bus_unown_name(own_id);return 0;}/<assert.h>/<glib.h>/<stdio.h>/<code>

同理,on_handle_set_version的參數在Building.c中有定義,不可隨便定義

5. gdbus_server.h

<code>/** =====================================================================================**       Filename:  gdbus_server.h**    Description:**        Version:  1.0*        Created:  10/31/2017 10:11:19 AM*       Revision:  none*       Compiler:  gcc**         Author:  qiaotsh (), [email protected]*   Organization:  www.neusoft.com** =====================================================================================*/#ifndef __GDBUS_SERVER_H_#define __GDBUS_SERVER_H_#define GDBUS_API  __attribute__((visibility("hidden")))GDBUS_API void GBusAcquired_Callback (GDBusConnection *connection,const gchar *name,gpointer user_data);GDBUS_API void GBusNameAcquired_Callback (GDBusConnection *connection,const gchar *name,gpointer user_data);GDBUS_API void GBusNameLost_Callback (GDBusConnection *connection,const gchar *name,gpointer user_data);#endif/<code>

gdbus_client.h是空的,因為我懶。common.h是空的,沒準以後會用上呢

6. autogen.sh

<code>#!/bin/shautoreconf --verbose --force --install --make || {echo 'autogen.sh failed';exit 1;}echoecho "Now you can 'configure' then 'make'"echo/<code>

7. configure.ac

<code>AC_INIT([gdbus-example], [0.1], [[email protected]])AC_CONFIG_AUX_DIR([build-aux])AC_CONFIG_MACRO_DIR([m4])AM_INIT_AUTOMAKE([foreign -Wall -Werror])AM_PROG_ARLT_INITAC_PROG_CCAC_CONFIG_HEADERS([config.h])AC_CONFIG_FILES([Makefile src/Makefile ])PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.40.2])PKG_CHECK_MODULES([GIO], [gio-unix-2.0 >= 2.40.2])AC_OUTPUT/<code>

8. 編譯方法如下

<code>./autogen.sh./configure $CONFIGURE_FLAGS –prefix=/usrmakemake install/<code>

生成gdbus_server 和gdbus_client

9. 執行效果如下

<code>gdbus_serverGBusAcquired_Callback has been invokedGBusAcquired_Callback the name = com.qiaotsh.Building.TestGBusAcquired_Callback the user_data = qiaotshGBusNameAcquired_Callback has been invokedEmit_Test_Status() is called.Emit_Test_Status() is called.Emit_Test_Status() is called.Emit_Test_Status() is called.Emit_Test_Status() is called.Emit_Test_Status() is called.Method call: hello worldEmit_Test_Status() is called.Emit_Test_Status() is called.Emit_Test_Status() is called.Emit_Test_Status() is called.Emit_Test_Status() is called.Emit_Test_Status() is called.Emit_Test_Status() is called.Emit_Test_Status() is called.Emit_Test_Status() is called.Emit_Test_Status() is called.Emit_Test_Status() is called.Emit_Test_Status() is called.Emit_Test_Status() is called.Emit_Test_Status() is called.Emit_Test_Status() is called.gdbus_clientsync reply = getSuccesssignal received 5signal received 5signal received 5signal received 5signal received 5signal received 5signal received 5signal received 5signal received 5signal received 5signal received 5signal received 5signal received 5/<code>


分享到:


相關文章: