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) -g
AM_CPPFLAGS = -I$(top_srcdir)/private-include

BUILT_SOURCES = Building.c Building.h
dist_noinst_DATA = Building.xml


bin_PROGRAMS = gdbus_server gdbus_client

gdbus_server_SOURCES = gdbus_server.c \\
Building.c Building.h
gdbus_server_LDADD = $(GLIB_LIBS) $(GIO_LIBS)

gdbus_client_SOURCES = gdbus_client.c \\
BuildingClient.c BuildingClient.h
gdbus_client_LDADD = $(GLIB_LIBS) $(GIO_LIBS)

Building.c Building.h : Building.xml
gdbus-codegen  --interface-prefix=com.qiaotsh.Building --generate-c-code=Building $<

MOSTLYCLEANFILES = $(BUILT_SOURCES)/<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/sh
autoreconf --verbose --force --install --make || {
echo 'autogen.sh failed';
exit 1;
}

echo
echo "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_AR

LT_INIT

AC_PROG_CC

AC_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=/usr

make

make install/<code>

生成gdbus_server 和gdbus_client

9. 执行效果如下

<code>gdbus_server

GBusAcquired_Callback has been invoked

GBusAcquired_Callback the name = com.qiaotsh.Building.Test

GBusAcquired_Callback the user_data = qiaotsh

GBusNameAcquired_Callback has been invoked

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.

Method call: hello world

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.

Emit_Test_Status() is called.

gdbus_client

sync reply = getSuccess

signal received 5

signal received 5

signal received 5

signal received 5

signal received 5

signal received 5

signal received 5

signal received 5

signal received 5

signal received 5

signal received 5

signal received 5

signal received 5/<code>


分享到:


相關文章: