gdbus demo程序简介

近期想要写一个gdbus的demo程序,查阅了一下资料,发现貌似gdbus之间的IPC通信分为两种,一种是基于system总线,一种是基于session,我通过session通信的方式简单写了一个p2p的demo程序。
首先通过gdbus-codegen 生成.h 和.c 文件,然后通过glib gio的接口分别写了一个客户端和服务端,客户端通过method与服务端进行同步通信,服务端通过signal 主动向客户端发送信号通知。
服务端流程图如下

服务端流程图

客户端流程图如下

这里写图片描述

程序使用automake进行构建,结构如下
├── 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
下面把各文件的内容贴上
Building.xml

<?xml version="1.0" encoding="UTF-8"?>
<node>
  <interface name="com.qiaotsh.Building.Test">
    <method name="SetVersion">
      <arg name="version" type="s" direction="in"/>
      <arg name="reply" type="s" direction="out"/>
    </method>
    <signal name="TestStatus">
      <arg name="status" type="i"/>
    </signal>
  </interface>
</node>

method中s代表字符串,i代表数字,其中direction中in代表入参,即发送的值,out代表出参,即获取的值

signal代表服务端发送的信号,此处表示发送一个数字

Makefile.am

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)

Makefile.am中使用gdbus-codegen对Building.xml进行处理,生成Building.h Building.c,
–interface-prefix代表省略前缀名com.qiaotsh.Building,这样在生成文件中将以Test为函数开头,否则字符串看起来比较冗余,是comqiaoBuildingtest开头,目的是增强可读性,–generate-c-code代表生成C语言代码

gdbus_client.c

/*
 * =====================================================================================
 *
 *       Filename:  gdbus_client.c
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  02/17/2017 08:28:34 AM
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  qiaotsh 
 *
 * =====================================================================================
 */
#include <glib.h>
#include <gio/gio.h>
#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;
}

值得注意的是test_status_handler的参数不是随便定义的,具体形式在Building.c中有详细描述

gdbus_server.c

/*
 * =====================================================================================
 *
 *       Filename:  gdbus_client.c
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  02/17/2017 08:28:34 AM
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  qiaotsh
 *
 * =====================================================================================
 */
#include<stdio.h>
#include<gio/gio.h>
#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;
}

同理,on_handle_set_version的参数在Building.c中有定义,不可随便定义
gdbus_server.h

/*
 * =====================================================================================
 *
 *       Filename:  gdbus_server.h
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  10/31/2017 10:11:19 AM
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  qiaotsh
 * =====================================================================================
 */
#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

gdbus_client.h是空的,因为我懒

common.h是空的,没准以后会用上呢

autogen.sh

#!/bin/sh
autoreconf --verbose --force --install --make || {
 echo 'autogen.sh failed';
 exit 1;
}

echo
echo "Now you can 'configure' then 'make'"
echo

configure.ac

AC_INIT([gdbus-example], [0.1], [onurmark1@gmail.com])

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

编译方法如下
./autogen.sh
./configure $CONFIGURE_FLAGS –prefix=/usr
make
make install

生成gdbus_server 和gdbus_client

执行效果如下
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
signal received 5

  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值