一、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
- g_main_loop_new(NULL, FALSE);
- g_bus_get_sync(YANLIN_GDBUS_EXAMPLE_BUS, NULL, &pConnError);
- 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
- g_main_loop_new(NULL, FALSE);
- 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
来源:CSDN
作者:yanlinembed
链接:https://blog.csdn.net/yanlinembed/article/details/46985605