1. 程式人生 > >GDBus 通訊機制介紹及Demo版本

GDBus 通訊機制介紹及Demo版本

一、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

相關推薦

GDBus 通訊機制介紹Demo版本

一、DBus通訊概念 DBus通訊是IPC通訊機制的一種方式,它有兩種模式,分別為:session(會話模式)、system(匯流排模式)。 匯流排模式:採用匯流排模式時,系統需要維護一個DBus Daemon,每個DBus的請求通過DBus Daemon轉

QT程序間通訊詳細介紹QProcess機制分析

1、QT通訊機制 為了更好的實現QT的資訊互動,在QT系統中建立了較為完善的通訊機制。QT的通訊可分為QT內部通訊和外部通訊兩大類。對於這兩類通訊機制及應用場合做如以下分析: (1)QT內部物件間通訊 在圖形使用者介面程式設計中,經常需要將一個視窗部件的變化通知給

Python使用Ctypes與C/C++ DLL檔案通訊過程介紹例項分析

專案中可能會經常用到第三方庫,主要是出於程式效率考慮和節約開發時間避免重複造輪子。無論第三方庫開源與否,程式語言是否與當前專案一致,我們最終的目的是在當前程式設計環境中呼叫庫中的方法並得到結果或者藉助庫中的模組實現某種功能。這個過程會牽涉到很多東西,本篇文章將簡要的介紹一下該過程的一些問題。 1.背景 多

Andrid6.0許可權機制介紹處理

在Android M新增的許可權機制中,Google將許可權分為兩類: Normal Permissions(普通許可權):不涉及使用者隱私,不需要使用者進行授權,比如訪問網路等 android.permission.ACCESS_LOCATION_

NSNotificationCenter訊息通訊機制介紹(KVO)

作用:NSNotificationCenter是專門供程式中不同類間的訊息通訊而設定的. 註冊通知:即要在什麼地方接受訊息                [[NSNotificationCenter defaultCenter]  addObserver:self selector:@selector(m

IOS NSNotificationCenter訊息通訊機制介紹

訊息傳送機構:舉例說明 在有需要的類中,傳送訊息 //傳送訊息出去,這裡的物件是一個數組:saveImageArray [[NSNotificationCenter defaultCenter] postNotificationName:@"postData" object:saveImageArray];

UDP通訊知識介紹簡易教程

     使用UDP協議進行資訊的傳輸之前不需要建議連線。換句話說就是客戶端向伺服器傳送資訊,客戶端只需要給出伺服器的ip地址和埠號,然後將資訊封裝到一個待發送的報文中並且傳送出去。至於伺服器端是否存在,或者能否收到該報文,客戶端根本不用管。           單播

Android下的兩種http通訊機制介紹

Android網路通訊經常會用到http通訊機制,而基本上目前有兩個實現方式:HttpUrlConnection和HttpClient。 HttpUrlConnection和HttpClient的關係 在研究一些開源網路請求框架時發現在Andr

Django預設許可權機制介紹實踐

演示Django版本為當前最新版本v2.2 當Django配置檔案中的INSTALL_APPS包含了django.contrib.auth時,就預設啟用了一個簡單的許可權系統,提供了為使用者或組分配許可權的方法 之所以說簡單呢?主要是因為: 預設的許可權系統是基於表的控制,許可權最小粒度是表 也就是說

架構師之路--搜索業務和技術介紹容錯機制

朋友 單節點 adb 一致性 公司 一個 memcache 消息通知 包括  今天和搜索部門一起做了一下MQ的遷移,順便交流一下業務和技術。發現現在90後小夥都挺不錯。我是指能力和探究心。我家男孩,不招女婿。   在前面的文章中也提到,我們有媒資庫(樂視視頻音頻本身內容)

Spark內建框架rpc通訊機制RpcEnv基礎設施-Spark商業環境實戰

本套系列部落格從真實商業環境抽取案例進行總結和分享,並給出Spark原始碼解讀及商業實戰指導,請持續關注本套部落格。版權宣告:本套Spark原始碼解讀及商業實戰歸作者(秦凱新)所有,禁止轉載,歡迎學習。 Spark商業環境實戰及調優進階系列 Spark商業環境實戰-Spark內建框架rpc通訊機制及

Parallels Desktop 12最新版軟件介紹版本信息

img 虛擬系統 too roi mar top cto 功能介紹 ffffff 軟件介紹:Parallels Desktop 13 Mac版是Mac平臺上一款非常經典的Mac虛擬機軟件,Parallels Desktop可以在你的Mac電腦上安裝一個windows系統,讓

Parallels Desktop 12最新版軟體介紹版本資訊

版權歸作者所有,任何形式轉載請聯絡作者。 作者:你們都(來自豆瓣) 來源:https://www.douban.com/note/690309442/ 軟體介紹: Parallels Desktop 13 Mac版是Mac平臺上一款非常經典的Mac虛擬機器軟體,Parallels Des

Eureka控制檯相關介紹自我保護機制解說

一、Eureka控制檯簡介 對於Eureka大家都有所瞭解,不懂請參考:https://blog.csdn.net/forezp/article/details/81040925 1.進入Eureka控制檯首頁,首先看HOME頁的頭部 【System Stat

golang第二課---go語言介紹版本檢視

跨平臺特性 Go語言和Java,Python一樣,也是支援跨平臺的。另外,Go語言還有黑科技:支援跨平臺編譯。比如你手頭只有Mac系統,而你的使用者有Linux和Windows的,他們也想使用你的Go語言程式,你可以通過交叉編譯出Linux和Windows上的可執行

Jenkins持續整合介紹外掛安裝版本更新演示(一)--技術流ken

  Jenkins介紹    Jenkins是一個開源軟體專案,是基於Java開發的一種持續整合工具,用於監控持續重複的工作,旨在提供一個開放易用的軟體平臺,使軟體的持續整合變成可能。 Jenkins功能包括: 1、持續的軟體版本釋出/測試專案。 2、監控外部呼叫執行

程序間通訊的幾種方式的介紹比較

程序間通訊 就是在不同程序之間傳播或交換資訊,那麼不同程序之間存在著什麼雙方都可以訪問的介質呢?程序的使用者空間是互相獨立的,一般而言是不能互相訪問的,唯一的例外是共享記憶體區。但是,系統空間卻是“公共場所”,所以核心顯然可以提供這樣的條件。除此以外,那就是雙方都可以訪問的外設了。在這個意義上,兩個

Kubernetes儲存系統介紹機制實現

一、Kubernetes中儲存的應用場景 在Kubernetes中部署和執行的服務大致分為: 1. 無狀態服務 Kubernetes使用ReplicaSet來保證一個服務的例項數量,如果說某個Pod例項由於某種原因掛掉或崩潰,ReplicaSet會立刻用這個Pod的模版

Android每天一個知識點+Demo—跨程序通訊機制AIDL入門

一 Why-為什麼要用AIDL 沙箱理念:在Android中,每個應用(Application)程式都執行在獨立的程序中,無法直接呼叫到其他應用的資源。當一個應用被執行時,一些操作是被限制的,比如訪問記憶體,訪問感測器等等。 好處:這也保證了當其中一個程式出現異常而不會影

DS1302時鐘模組介紹與USRAT HMI通訊

一、DS1302時鐘模組 現在流行的序列時鐘電路很多,如DS1302、 DS1307、PCF8485等。這些電路的介面簡單、價格低廉、使用方便,被廣泛地採用。 DS1302 是美國DALLAS公司推出的一種高效能、低功耗、帶RAM的實時時鐘電路,它可以對年、月、日、周、時