GDBus 通信机制介绍及Demo版本

跟風遠走 提交于 2019-12-06 07:43:46

一、DBus通信概念

DBus通信是IPC通信机制的一种方式,它有两种模式,分别为:session(会话模式)、system(总线模式)。

总线模式:采用总线模式时,系统需要维护一个DBus Daemon,每个DBus的请求通过DBus Daemon转发。这种模式Server只需要维护一个与DBus Daemon的链接,结构清晰,可以通过广播的方式发送消息到各个Client。

会话模式:这种模式一般称之为点对点的星型结构,Client与Server之间是直接的Peer2Peer的连接,少了DBus Daemon的中转,因此性能较好。

注意:在使用DBus通信前,需要保证系统安装了GIO_LIBS库,如果Linux环境还没有安装GIO_LIBS,请使用以下命令进行安装:

yum install libgnomeui-devel

二、DBus Demo介绍

DBus的通信机制是Server-Client模式,Server需要提供一个XML(eg: com.Yanlin.Gdbus.Example.xml)文档给Client端去说明DBus Server提供的interface name、signal name及它的arg name、 type、 direction、method name及它的arg name、 type、 direction。

com.Yanlin.Gdbus.Example.xml

<node>
  <interface name="com.Yanlin.Gdbus.Example">

    <signal name="MySignal1">
      <arg name="Value" type="s"/>
    </signal>

    <signal name="MySignal2">
      <arg name="Value" type="(is)"/>
    </signal>

    <method name="MyMethod1">
      <arg name="InArg"  direction="in"  type="s"/>
      <arg name="OutArg" direction="out" type="s"/>
    </method>

    <method name="MyMethod2">
      <arg name="InArg"  direction="in"  type="(ii)"/>
      <arg name="OutArg" direction="out" type="(si)"/>
    </method>

  </interface>
</node>

Client端需要用这个XML文档去产生两个文件-generated.h and -generated.c 另外,Server还需要提供一个header文档(eg: dbusCommon.h)去说明GDBus type、DBus name、object path。

dbusCommon.h

#ifndef YANLIN_GDBUS_EXAMPLE_H
#define YANLIN_GDBUS_EXAMPLE_H

#include <gio/gio.h> /* Bus define */

#define YANLIN_GDBUS_EXAMPLE_BUS         G_BUS_TYPE_SESSION
#define YANLIN_GDBUS_EXAMPLE_BUS_NAME    "com.yanlin.Gdbus.Example"
#define YANLIN_GDBUS_EXAMPLE_OBJECT_PATH "/com/yanlin/Gdbus/Example"

#endif
  • 程序架构大致会按照这样一个思路:
    Server、Client端会首先依赖XML产生的-generated.h and -generated.c两个文件封装相应的接口而产生两个静态库文件(在这里静态或者动态库都是一样)。然后编写两个应用测试程序去测试静态库导出的DBus同步、异步接口。

*Synchronize interface in the terminal of client.

gboolean
cyanlin_gdbus_example_call_my_method1_sync (
    CYanlinGdbusExample *proxy,
    const gchar *arg_InArg,
    gchar **out_OutArg,
    GCancellable *cancellable,
    GError **error)

gboolean
cyanlin_gdbus_example_call_my_method2_sync (
    CYanlinGdbusExample *proxy,
    GVariant *arg_InArg,
    GVariant **out_OutArg,
    GCancellable *cancellable,
    GError **error)

*Asynchronize interface in the terminal of client.

void
cyanlin_gdbus_example_call_my_method1 (
    CYanlinGdbusExample *proxy,
    const gchar *arg_InArg,
    GCancellable *cancellable,
    GAsyncReadyCallback callback,
    gpointer user_data)
gboolean
cyanlin_gdbus_example_call_my_method1_finish (
    CYanlinGdbusExample *proxy,
    gchar **out_OutArg,
    GAsyncResult *res,
    GError **error)

void
cyanlin_gdbus_example_call_my_method2 (
    CYanlinGdbusExample *proxy,
    GVariant *arg_InArg,
    GCancellable *cancellable,
    GAsyncReadyCallback callback,
    gpointer user_data)
gboolean
cyanlin_gdbus_example_call_my_method2_finish (
    CYanlinGdbusExample *proxy,
    GVariant **out_OutArg,
    GAsyncResult *res,
    GError **error)

DBus connect in the Client-side

  • critical interface
    1. g_main_loop_new(NULL, FALSE);
    2. g_bus_get_sync(YANLIN_GDBUS_EXAMPLE_BUS, NULL, &pConnError);
    3. cyanlin_gdbus_example_proxy_new_sync(pConnection,
      G_DBUS_PROXY_FLAGS_NONE,
      YANLIN_GDBUS_EXAMPLE_BUS_NAME,
      YANLIN_GDBUS_EXAMPLE_OBJECT_PATH,
      NULL,
      &pProxyError);
bool InitDBusCommunication(void)
{
    bool bRet = TRUE;
    GError *pConnError = NULL;
    GError *pProxyError = NULL;

    g_type_init();  /** initial for usage of "g" types */

    g_print("InitDBusCommunication: Client started.\n");

    do{
        bRet = TRUE;
        pLoop = g_main_loop_new(NULL, FALSE);   /** create main loop, but do not start it.*/

        /** First step: get a connection */
        pConnection = g_bus_get_sync(YANLIN_GDBUS_EXAMPLE_BUS, NULL, &pConnError);

        if (NULL == pConnError){
            /** Second step: try to get a connection to the given bus.*/
            pProxy = cyanlin_gdbus_example_proxy_new_sync(pConnection,
                                        G_DBUS_PROXY_FLAGS_NONE,
                                        YANLIN_GDBUS_EXAMPLE_BUS_NAME,
                                        YANLIN_GDBUS_EXAMPLE_OBJECT_PATH,
                                        NULL,
                                        &pProxyError);
            if (0 == pProxy){
                g_print("InitDBusCommunication: Failed to create proxy. Reason: %s.\n", pProxyError->message);
                g_error_free(pProxyError);
                bRet = FALSE;
            }


        }
        else{
            g_print("InitDBusCommunication: Failed to connect to dbus. Reason: %s.\n", pConnError->message);
            g_error_free(pConnError);
            bRet = FALSE;
        }
    }while(FALSE == bRet);

    if (TRUE == bRet){
        /** Third step: Attach to dbus signals */
        registerClientSignalHandler(pProxy);
    }

    thread_create();
}

DBus register in the Server-side

  • critical interface
    1. g_main_loop_new(NULL, FALSE);
    2. g_bus_own_name(YANLIN_GDBUS_EXAMPLE_BUS,
      YANLIN_GDBUS_EXAMPLE_BUS_NAME,
      G_BUS_NAME_OWNER_FLAGS_NONE,
      &bus_acquired_cb,
      &name_acquired_cb,
      &name_lost_cb,
      NULL,
      NULL);
bool InitDBusCommunicationServer(void)
{
    bool bRet = TRUE;

    /** init for usage of "g" types */
    g_type_init();

    g_print("InitDBusCommunicationServer: Server started.\n");

    /** create main loop, but do not start it. */
    pLoop = g_main_loop_new(NULL, FALSE);

    /** first step: connect to dbus */
    (void)g_bus_own_name(YANLIN_GDBUS_EXAMPLE_BUS,
                        YANLIN_GDBUS_EXAMPLE_BUS_NAME,
                        G_BUS_NAME_OWNER_FLAGS_NONE,
                        &bus_acquired_cb,
                        &name_acquired_cb,
                        &name_lost_cb,
                        NULL,
                        NULL);
    /** emit my signal1 every 1 second to trigger example communication */
    g_timeout_add(1000, (GSourceFunc)Emit_My_signal1, NULL);

    /** emit my signal2 every2 second to trigger example communication */
    g_timeout_add(2000, (GSourceFunc)Emit_My_Signal2, NULL);

    thread_create();

    return bRet;    
}

详细代码:

  • libClient.c
/**
    Header files
*/

/**
    Own header
*/
#include "dbusCommon.h"
#include "libclient.h"

/**
    Generated headers
*/
#include "Example-generated.h"

/**
    System header
*/
#include <gio/gio.h>    /** GIO for dbus*/
#include <glib-2.0/glib.h>  /** GLIB for main loop*/  
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>

/**
    instance init
*/
static GMainLoop *pLoop = NULL;
static GDBusConnection *pConnection = NULL;
static CYanlinGdbusExample *pProxy = NULL;
static gulong g_RetSignalHandler[RET_SIGNAL_HANDLE_SIZE];
static S_SIGNAL_CALLBACK g_signal_callback;
static S_METHOD_CALLBACK g_method_callback;

static gboolean My_Signal_1_Handler(CYanlinGdbusExample *object, const gchar *arg, gpointer userdata)
{
    if (NULL != g_signal_callback.callback1){
        g_signal_callback.callback1(arg);
    }

    return TRUE;
}

static gboolean My_Signal_2_Handler(CYanlinGdbusExample *object,  GVariant *arg, gpointer userdata)
{
    /** get the value from GVariant */
    gint int_arg = 0;
    gchar *char_arg = NULL;

    g_variant_get(arg, "(is)", &int_arg, &char_arg);

    if (NULL != g_signal_callback.callback2){
        g_signal_callback.callback2(int_arg, char_arg);
    }
    g_free(char_arg);

    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);
    }
}
bool registerClientSignalHandler(CYanlinGdbusExample *pProxy)
{
    g_print("registerClientSignalHandler call.\n");
    g_RetSignalHandler[0] = g_signal_connect(pProxy, "notify::g-name-owner", G_CALLBACK(cb_OwnerNameChangedNotify), NULL);
    g_RetSignalHandler[1] = g_signal_connect(pProxy, "my-signal1", G_CALLBACK(My_Signal_1_Handler), NULL);
    g_RetSignalHandler[2] = g_signal_connect(pProxy, "my-signal2", G_CALLBACK(My_Signal_2_Handler), NULL);
    return TRUE;
}

void registerSignalCallback(S_SIGNAL_CALLBACK *callback)
{
    if (NULL != callback){
        memcpy(&g_signal_callback, callback, sizeof(S_SIGNAL_CALLBACK));
    }
    else{
            g_print("registerSignalCallback: parameter point is NULL");
    }
}

void registerMethodCallback(S_METHOD_CALLBACK *callback)
{
    if (NULL != callback){
        memcpy(&g_method_callback, callback, sizeof(S_SIGNAL_CALLBACK));
    }
    else{
            g_print("registerMethodCallback: parameter point is NULL");
    }
}

static void MethodCallback_1(GObject* source_object, GAsyncResult* res, gpointer userdata)
{
    g_print("client MethodCallback_1 call.\n");

    gchar* out_arg = NULL;
    GError* pError = NULL;

    cyanlin_gdbus_example_call_my_method1_finish(pProxy, &out_arg, res, &pError);

    if(NULL == pError){
        if(NULL != g_method_callback.callback1){
            g_method_callback.callback1(out_arg, pError);
            g_free(out_arg);
        }
    }
    else{
        g_error_free(pError);
    }
}
void myMethodAsync_1(const char* in_arg)
{
    g_print("client myMethodAsync_1 call, in_arg = %s.\n", in_arg);

    cyanlin_gdbus_example_call_my_method1(pProxy, in_arg, NULL, MethodCallback_1, NULL);
    return;
}

void myMethod_1(const gchar *in_arg, gchar** out_arg, GError** pError)
{
    cyanlin_gdbus_example_call_my_method1_sync(pProxy, in_arg, out_arg, NULL, pError);

    if (*pError == NULL){
        g_print("client myMethod_1 call, in_arg = %s out_arg = %s.\n", in_arg, *out_arg);
            g_free(*out_arg);
    }
    else{
            g_print("client myMethod_1: Failed to call method. Reason: %s.\n", (*pError)->message);
            g_error_free(*pError);
    }

    return; 
}

static void MethodCallback_2(GObject* source_object, GAsyncResult* res, gpointer user_data)
{
    g_print("client MethodCallback_2 call.\n");

    GVariant *out_arg = NULL;
    GError *pError = NULL;
    gchar *out_arg1 = NULL;
    gint out_arg2 = 0;

    cyanlin_gdbus_example_call_my_method2_finish(pProxy, &out_arg, res, &pError);
    if (NULL == pError){
        /** get the result from the output paramter */
        g_variant_get(out_arg, "(si)", &out_arg1, &out_arg2);
        if(NULL != g_method_callback.callback2){
            g_method_callback.callback2(out_arg1, out_arg2, pError);
            g_free(out_arg1);
        }
    }
    else{
        g_error_free(pError);
    }

}
void myMethodAsync_2(const gint in_arg1, const gint in_arg2)
{
    g_print("client myMethodAsync_2 call, in_arg1 = %d, in_arg2 = %d.\n", in_arg1, in_arg2);

    GVariant *in_arg = g_variant_new("(ii)", in_arg1, in_arg2);
    cyanlin_gdbus_example_call_my_method2(pProxy, in_arg, NULL, MethodCallback_2, NULL);

    return;
}

void myMethod_2(const gint in_arg1, const gint in_arg2, gchar **out_arg1, gint *out_arg2, GError** pError)
{
    GVariant *in_arg = NULL;
    GVariant *out_arg = NULL;
    GError *Error = NULL;

    /** generate the input parameters */
    in_arg = g_variant_new("(ii)", in_arg1, in_arg2);

    /** call the server's dbus methods */
    cyanlin_gdbus_example_call_my_method2_sync(pProxy, in_arg, &out_arg, NULL, pError);
    if(NULL == *pError){
        /** get the result from the output parameter */
        g_variant_get(out_arg, "(si)", out_arg1, out_arg2);
        g_print("client myMethod_2 call, in_arg1 = %d, in_arg2 = %d, out_arg1 = %s, out_arg2 = %d.\n", in_arg1, in_arg2, *out_arg1, *out_arg2);
            g_free(*pError);
    }
    else{
            g_print("client myMethod_2: Failed to call method. Reason: %s.\n", (*pError)->message);
            g_error_free(*pError);
    }

    return; 
}

void *run(void* arg)
{
    g_print("run call in the client.\n");
    /** start the main event loop which manages all available sources of events */
    g_main_loop_run(pLoop);

    return ((void*)0);
}

int thread_create(void)
{
    int err;
    pthread_t thr;

    err = pthread_create(&thr, NULL, run, NULL);

    if(0 != err){
            g_print("Can't create thread: %s\n", strerror(err));
    }
    else{       
            g_print("New thread created: %s\n", strerror(err));
    }

    return err;
}

bool ExampleDBusServiceIsReady(void)
{
    gchar *owner_name = NULL;
    owner_name = g_dbus_proxy_get_name_owner((GDBusProxy*)pProxy);
    if(NULL != owner_name)
    {
        g_print("Owner Name: %s\n", owner_name);        
        g_free(owner_name);
        return true;
    }
    else
    {   
        g_print("Owner Name is NULL.");     
        return false;
    }
}

bool InitDBusCommunication(void)
{
    bool bRet = TRUE;
    GError *pConnError = NULL;
    GError *pProxyError = NULL;

    g_type_init();  /** initial for usage of "g" types */

    g_print("InitDBusCommunication: Client started.\n");

    do{
        bRet = TRUE;
        pLoop = g_main_loop_new(NULL, FALSE);   /** create main loop, but do not start it.*/

        /** First step: get a connection */
        pConnection = g_bus_get_sync(YANLIN_GDBUS_EXAMPLE_BUS, NULL, &pConnError);

        if (NULL == pConnError){
            /** Second step: try to get a connection to the given bus.*/
            pProxy = cyanlin_gdbus_example_proxy_new_sync(pConnection,
                                        G_DBUS_PROXY_FLAGS_NONE,
                                        YANLIN_GDBUS_EXAMPLE_BUS_NAME,
                                        YANLIN_GDBUS_EXAMPLE_OBJECT_PATH,
                                        NULL,
                                        &pProxyError);
            if (0 == pProxy){
                g_print("InitDBusCommunication: Failed to create proxy. Reason: %s.\n", pProxyError->message);
                g_error_free(pProxyError);
                bRet = FALSE;
            }


        }
        else{
            g_print("InitDBusCommunication: Failed to connect to dbus. Reason: %s.\n", pConnError->message);
            g_error_free(pConnError);
            bRet = FALSE;
        }
    }while(FALSE == bRet);

    if (TRUE == bRet){
        /** Third step: Attach to dbus signals */
        registerClientSignalHandler(pProxy);
    }

    thread_create();
}

bool DeInitDBusCommunication(void)
{
    bool bRet = FALSE;

    if(0 != pLoop){
        g_main_loop_quit(pLoop);
        g_main_loop_unref(pLoop);
        bRet = TRUE;
    }

    return bRet;
}
  • libServer.c
/**
    Header files
*/

/** 
    Own header
*/
#include "dbusCommon.h"
#include "libServer.h"

/** 
    System header
*/
#include <gio/gio.h>   // GIO for dbus
#include <glib-2.0/glib.h>   // GLIB for main loop
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>

/**
    Generated headers
*/
#include "Example-generated.h"

/**
    Instance init
*/
static GMainLoop         *pLoop     = NULL;
static CYanlinGdbusExample *pSkeleton = NULL;
static int callNum = 0;

/**
    Normal functions
*/
static gboolean Emit_My_signal1(gconstpointer p)
{
    g_print("Emit_My_Signal1() is called.\n");

    gchar buf[20];
    memset(buf, 0, 20);
    callNum++;
    sprintf(buf, "Server Signal1(%d)", callNum);

    cyanlin_gdbus_example_emit_my_signal1(pSkeleton, buf);

    return TRUE;
}

static gboolean Emit_My_Signal2(gconstpointer p)
{
    g_print("Emit_My_Signal2() is called.\n");

    callNum++;
    GVariant *payload = g_variant_new("(is)", callNum, "Server Signal2");

    cyanlin_gdbus_example_emit_my_signal2(pSkeleton, payload);

    return TRUE;
}

static gboolean My_Method1(CYanlinGdbusExample     *object,
                               GDBusMethodInvocation *invocation,
                               const gchar           *in_arg,
                               gpointer               user_data)
{
    g_print("Server MyMethod1 call. Parameter: %s.\n", in_arg);

    in_arg = "Server My_Method1 to output.";

    cyanlin_gdbus_example_complete_my_method1(object, invocation, in_arg);

    return TRUE;
}

static gboolean My_Method2(CYanlinGdbusExample     *object,
                               GDBusMethodInvocation *invocation,
                               GVariant           *in_arg,
                               gpointer               user_data)
{
  gint in_arg1 = 0;
  gint in_arg2 = 0;
  gint out_arg2 = 0;
  gchar *out_arg1 = "Server MyMethod2 to output.";
  GVariant *out_arg = NULL;

  /** Get the input parameters */
  g_variant_get(in_arg, "(ii)", &in_arg1, &in_arg2);

  g_print("Server MyMethod2 call. Parameter: in_arg1 = %d , in_arg2 = %d.\n", in_arg1, in_arg2);

  /** Generate the output parameters */
  out_arg2 = in_arg1 + in_arg2;
  out_arg = g_variant_new("(si)", out_arg1, out_arg2);

  cyanlin_gdbus_example_complete_my_method2(object, invocation, out_arg);

  return TRUE;

}

static void bus_acquired_cb(GDBusConnection *connection,
                                const gchar     *bus_name,
                                gpointer         user_data)
{
    GError *pError = NULL;

    /** Second step: Try to get a connection to the given bus. */
    pSkeleton = cyanlin_gdbus_example_skeleton_new();

    /** Third step: Attach to dbus signals. */
    (void) g_signal_connect(pSkeleton, "handle-my-method1", G_CALLBACK(My_Method1), NULL);
    (void) g_signal_connect(pSkeleton, "handle-my-method2", G_CALLBACK(My_Method2), NULL);

    /** Fourth step: Export interface skeleton. */
    (void) g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(pSkeleton),
                                              connection,
                                              YANLIN_GDBUS_EXAMPLE_OBJECT_PATH,
                                              &pError);
    if(pError != NULL){
        g_print("Error: Failed to export object. Reason: %s.\n", pError->message);
        g_error_free(pError);
        g_main_loop_quit(pLoop);
    }
}

static void name_acquired_cb(GDBusConnection *connection,
                                     const gchar     *bus_name,
                                     gpointer         user_data)
{
    g_print("name_acquired_cb call, Acquired bus name: %s.\n", YANLIN_GDBUS_EXAMPLE_BUS_NAME);
}

static void name_lost_cb(GDBusConnection *connection,
                             const gchar     *bus_name,
                             gpointer         user_data)
{
    if(connection == NULL)
    {
        g_print("name_lost_cb call, Error: Failed to connect to dbus.\n");
    }
    else
    {
        g_print("name_lost_cb call, Error: Failed to obtain bus name: %s.\n", YANLIN_GDBUS_EXAMPLE_BUS_NAME);
    }

    g_main_loop_quit(pLoop);
}

void* run(void* para)
{
    g_print("run call in the server.\n");
        /** Start the Main Event Loop which manages all available sources of events */
    g_main_loop_run( pLoop );

    return ((void*)0);
}

int thread_create(void)
{
    int err;
    pthread_t thr;

    err = pthread_create(&thr, NULL, run, NULL);

    if (err != 0)
    {
        g_print("Can't create thread: %s\n", strerror(err));
    }
    else
    {
        g_print("New thread created: %s\n", strerror(err));
    }

    return err;
}


bool InitDBusCommunicationServer(void)
{
    bool bRet = TRUE;

    /** init for usage of "g" types */
    g_type_init();

    g_print("InitDBusCommunicationServer: Server started.\n");

    /** create main loop, but do not start it. */
    pLoop = g_main_loop_new(NULL, FALSE);

    /** first step: connect to dbus */
    (void)g_bus_own_name(YANLIN_GDBUS_EXAMPLE_BUS,
                        YANLIN_GDBUS_EXAMPLE_BUS_NAME,
                        G_BUS_NAME_OWNER_FLAGS_NONE,
                        &bus_acquired_cb,
                        &name_acquired_cb,
                        &name_lost_cb,
                        NULL,
                        NULL);
    /** emit my signal1 every 1 second to trigger example communication */
    g_timeout_add(1000, (GSourceFunc)Emit_My_signal1, NULL);

    /** emit my signal2 every2 second to trigger example communication */
    g_timeout_add(2000, (GSourceFunc)Emit_My_Signal2, NULL);

    thread_create();

    return bRet;    
}

bool DeinitDBusCommunicationServer(void)
{
    bool bRet = FALSE;
    if(0 != pLoop){
        g_main_loop_quit(pLoop);
        g_main_loop_unref(pLoop);
        bRet = TRUE;
    }

    return bRet;

}
  • CltExample.c
/**
    Header files
*/

#include "libclient.h"

/**
    Callback function
*/

void SignalCallback_1(const gchar* arg)
{
    g_print("Signal_1_Callback: Paramater value: %s.\n", arg);

    return;
}

void SignalCallback_2(const gint int_arg, const gchar* str_arg)
{
    g_print("Signal_2_Callback: Int value: %d, String value: %s\n", int_arg, str_arg);

    return;
}

void MethodCallback1(const gchar* arg, const GError* error)
{
    if (error == NULL)
    {
            g_print("Method1Callback: return value: %s.\n", arg);
    }
    else
    {
            g_print("Method1Callback: error message: %s.\n", error->message);
    }

    return;
}

void MethodCallback2(const gchar* out_arg1, const gint out_arg2, GError* error)
{
    if (error == NULL)
    {
            g_print("Method2Callback: return value: (%s, %d).\n", out_arg1, out_arg2);
    }
    else
    {
            g_print("Method2Callback: error message: %s.\n", error->message);
    }

    return;
}


int main(void)
{
    S_SIGNAL_CALLBACK signal_callback;
    S_METHOD_CALLBACK method_callback;

    signal_callback.callback1 = SignalCallback_1;
    signal_callback.callback2 = SignalCallback_2;

    registerSignalCallback(&signal_callback);

    method_callback.callback1 = MethodCallback1;
    method_callback.callback2 = MethodCallback2;

    registerMethodCallback(&method_callback);

    InitDBusCommunication();

    while(!ExampleDBusServiceIsReady());
#if 1
    const gchar *syncMehtod1Arg = "method1 synchronize call.";
    gchar *syncMethod1Out = NULL;
    GError *syncMethodError = NULL;

    myMethod_1(syncMehtod1Arg, &syncMethod1Out, &syncMethodError);
#endif
    gchar *asyncMethod1arg = "method1 asynchronize call.";
#if 1
    myMethodAsync_1(asyncMethod1arg);

    GError *syncMethod2Error = NULL;
    gint syncMethod2Arg1 = 12;
    gint syncMethod2Arg2 = 34;
    gchar *syncMethod2Out1 = NULL;
    gint syncMethod2Out2 = 0;

    myMethod_2(syncMethod2Arg1, syncMethod2Arg2, &syncMethod2Out1, &syncMethod2Out2, &syncMethod2Error);


    gint asyncMethod2Arg1 = 10;
    gint asyncMethod2Arg2 = 21;
    myMethodAsync_2(asyncMethod2Arg1, asyncMethod2Arg2);
#endif
    sleep(100);

    return 0;
}
  • SvrExample.c
#include "libServer.h"

int main(void)
{
    InitDBusCommunicationServer();

    sleep(100);

    return 0;
}
  • CMake file
# At least this cmake version is needed
CMAKE_MINIMUM_REQUIRED (VERSION 2.6)

# Define a project name for the SW package
PROJECT (YanLinDbusExample)

# version
SET(YanLinDbusExample_VERSION_MAJOR 1)
SET(YanLinDbusExample_VERSION_MINOR 0)

# XML file name
SET(XML_FILE_LIST com.Yanlin.Gdbus.Example.xml)
# generated file name
SET(XML_GEN_FILE_LIST Example-generated)

# check if the length of one of the above two lists is same as one of the other one
LIST(LENGTH XML_FILE_LIST XML_FILE_LIST_LEN)
LIST(LENGTH XML_GEN_FILE_LIST NAME_LIST_LEN)
MATH(EXPR XML_FILE_LIST_LEN "${XML_FILE_LIST_LEN}-1")
MATH(EXPR NAME_LIST_LEN "${NAME_LIST_LEN}-1")

IF(${XML_FILE_LIST_LEN} EQUAL ${NAME_LIST_LEN})
# generate files from XML
    FOREACH(INDEX RANGE 0 ${XML_FILE_LIST_LEN})
        LIST(GET XML_FILE_LIST ${INDEX} XML)
        LIST(GET XML_GEN_FILE_LIST ${INDEX} NAME_TMP)
        EXECUTE_PROCESS(COMMAND gdbus-codegen --interface com.Yanlin. --c-namespace CYanlin --generate-c-code ${PROJECT_BINARY_DIR}/${NAME_TMP} ${PROJECT_SOURCE_DIR}/${XML})
    ENDFOREACH(INDEX)
ELSE (${XML_FILE_LIST_LEN} EQUAL ${NAME_LIST_LEN})
    MESSAGE(FATAL_ERROR "The length (${XML_FILE_LIST_LEN}) of xml files list does not equal to the length(${NAME_LIST_LEN}) of the generated files name list")
ENDIF(${XML_FILE_LIST_LEN} EQUAL ${NAME_LIST_LEN})

# The library has to be dynamically linked to the header
INCLUDE_DIRECTORIES(/usr/include/glib-2.0)
INCLUDE_DIRECTORIES(/usr/lib/glib-2.0/include)
INCLUDE_DIRECTORIES(/usr/include/gio-unix-2.0)
INCLUDE_DIRECTORIES(/usr/lib/x86_64-linux-gnu/glib-2.0/include/)

INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/)
INCLUDE_DIRECTORIES(${PROJECT_BINARY_DIR}/)

link_directories(${PROJECT_BINARY_DIR}/)

set(SRCclient libClient.c ${PROJECT_BINARY_DIR}/Example-generated.c )
add_library(ExampleClientlib SHARED ${SRCclient})

#set(SRCclient libClient.c ${PROJECT_BINARY_DIR}/Example-generated.c )
#add_library(ExampleClientlib STATIC ${SRCclient})

set(SRCserver  libServer.c ${PROJECT_BINARY_DIR}/Example-generated.c)
add_library(ExampleServerlib STATIC ${SRCserver})

add_executable(SvrExample SvrExample.c)
target_link_libraries(SvrExample ${PROJECT_BINARY_DIR}/libExampleServerlib.a pthread gio-2.0 gobject-2.0 gmodule-2.0 gthread-2.0 rt glib-2.0)

add_executable(TCltExample CltExample.c)
target_link_libraries(TCltExample ${PROJECT_BINARY_DIR}/libExampleClientlib.so pthread gio-2.0 gobject-2.0 gmodule-2.0 gthread-2.0 rt glib-2.0)
  • libclient.h
#ifndef __LIB_CLIENT__
#define __LIB_CLIENT__

#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdbool.h>
#include <glib-2.0/glib.h>

#include "Example-generated.h"

#define RET_SIGNAL_HANDLE_SIZE 3

typedef void (*SIGNAL1CALLBACK)(const gchar*);
typedef void (*SIGNAL2CALLBACK)(const gint, const gchar*);
typedef struct signalcallback
{
    SIGNAL1CALLBACK callback1;  
    SIGNAL2CALLBACK callback2;
}S_SIGNAL_CALLBACK;

typedef void (*METHOD1CALLBACK)(const gchar*, const GError*);
typedef void (*METHOD2CALLBACK)(const gchar*, const gint, GError*);
typedef struct methodcallback
{
    METHOD1CALLBACK callback1;  
    METHOD2CALLBACK callback2;
}S_METHOD_CALLBACK;



static gboolean My_Signal_1_Handler(CYanlinGdbusExample *object, const gchar *arg, gpointer userdata);
static gboolean My_Signal_2_Handler(CYanlinGdbusExample *object,  GVariant *arg, gpointer userdata);
static void cb_OwnerNameChangedNotify(GObject *object, GParamSpec *pspec, gpointer userdata);
bool registerClientSignalHandler(CYanlinGdbusExample *pProxy);
void registerSignalCallback(S_SIGNAL_CALLBACK *callback);
void registerMethodCallback(S_METHOD_CALLBACK *callback);
static void MethodCallback_1(GObject* source_object, GAsyncResult* res, gpointer userdata);
void myMethodAsync_1(const char* in_arg);
void myMethod_1(const gchar *in_arg, gchar** out_arg, GError** pError);
static void MethodCallback_2(GObject* source_object, GAsyncResult* res, gpointer user_data);
void myMethodAsync_2(const gint in_arg1, const gint in_arg2);
void myMethod_2(const gint in_arg1, const gint in_arg2, gchar **out_arg1, gint *out_arg2, GError** pError);
void *run(void* arg);
int thread_create(void);
bool ExampleDBusServiceIsReady(void);
bool InitDBusCommunication(void);
bool DeInitDBusCommunication(void);
#endif
  • libServer.h
#ifndef __SERVER_H__
#define __SERVER_H__

#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdbool.h>

#include "Example-generated.h"
/** thread function's definition */

static gboolean Emit_My_signal1(gconstpointer p);
static gboolean Emit_My_Signal2(gconstpointer p);
static gboolean My_Method1(CYanlinGdbusExample* object, GDBusMethodInvocation* invocation, const gchar* in_arg, gpointer user_data);
static gboolean My_Method2(CYanlinGdbusExample* object, GDBusMethodInvocation* invocation, GVariant* in_arg, gpointer user_data);
static void bus_acquired_cb(GDBusConnection* connection, const gchar* bus_name, gpointer user_data);
static void name_acquired_cb(GDBusConnection* connection, const gchar* bus_name, gpointer user_data);
static void name_lost_cb(GDBusConnection* connection, const gchar* bus_name, gpointer user_data);
void* run(void*);
int thread_create(void);
bool InitDBusCommunicationServer(void);
bool DeinitDBusCommunicationServer(void);
#endif

目录树:

├── build
├── CltExample.c
├── CMakeLists.txt
├── com.Yanlin.Gdbus.Example.xml
├── dbusCommon.h
├── libClient.c
├── libclient.h
├── libServer.c
├── libServer.h
└── SvrExample.c

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