D-Bus学习(四):基础小例子(同步和异步)

  • Post author:
  • Post category:其他



从Tutorial中学习基本概念后,进入实战阶段,通过学习,我们给出连个小例子,同步例子和异步例子。


类型和GType的映射

在D-Bus编程中,基础类型和GType的映射表格如下。在后面的程序小例子中我们会看到具体如何对应。


D-Bus basic type

GType

Free function

Notes
BYTE G_TYPE_BOOLEAN
INT16 G_TYPE_INT Will be changed to a G_TYPE_INT16 once GLib has it
UINT16 G_TYPE_UINT Will be changed to a G_TYPE_UINT16 once GLib has it
INT32 G_TYPE_INT Will be changed to a G_TYPE_INT32 once GLib has it
UINT32 G_TYPE_UINT Will be changed to a G_TYPE_UINT32 once GLib has it
INT64 G_TYPE_GINT64
UINT64 G_TYPE_GUINT64
DOUBLE G_TYPE_DOUBLE
STRING G_TYPE_STRING g_free
OBJECT_PATH DBUS_TYPE_G_PROXY g_object_unref The returned proxy does not have an interface set; use dbus_g_proxy_set_interface to invoke methods

在D-Bus编程中,container类型和GType的映射表格如下:


D-Bus type signature

Description

GType

C typedef

Free function

Notes
as Array of strings G_TYPE_STRV char ** g_strfreev
v Generic value container G_TYPE_VALUE GValue * g_value_unset The calling conventions for values expect that method callers have allocated return values; see below.
a{ss} Dictionary mapping strings to strings

DBUS_TYPE_G_STRING_

STRING_HASHTABLE

GHashTable * g_hash_table_destroy


Makefile

在D-Bus中,使用了dbus-1 dbus-glib-1 glib-2.0(以Moblin 2.1为例)。Makefile的例子如下:

CC     = gcc

CFLAGS += -Wall -g

`pkg-config dbus-1 dbus-glib-1 glib-2.0 –cflags`


LIBS   += -Wall -g

`pkg-config dbus-1 dbus-glib-1 glib-2.0 –libs`

TARGET  = sample

OBJ    = $(TARGET).o

all: $(TARGET)

%o: %c

$(CC) $(CFLAGS) -c $< -o $@

$(TARGET): $(OBJ)

$(CC) $(LIBS) -o $(TARGET) $(OBJ)


同步的例子

同步即程序发出method call消息,等待method_return消息。下面是一个小例子,如果我们用dbus-send命令,可以使用:

dbus-send –session –print-reply –type=method_call –dest=org.freedesktop.Notifications / org.freedesktop.DBus.Introspectable.Introspect

在上一次学习中学习过。它的返回GType类型为G_TYPE_STRING,在C程序中对应char *。

#include <stdio.h>

#include <stdlib.h>

#include <dbus/dbus-glib.h>

int main( int argc , char ** argv)

{

GError * error;

DBusGConnection * connection;

DBusGProxy    * proxy;

char    * string;


/* GType初始化 */





g_type_init();


error = NULL;


/* dbus_g_bus_get用来建立连接,这里和session bus连接,也可以通过DBUS_BUS_SYSTEM与系统总线连接*/


connection =


dbus_g_bus_get

(DBUS_BUS_SESSION, & error);


if(connection == NULL){

g_printerr (“Failed to open connection to bus : %s/n”,error->message);

g_error_free( error);

exit( 1 );

}


/* Create a proxy object用来代表远端org.freedesktop.Notifications是系统带有的,可以使用DBUS_INTERFACE_INTROSPECTABLE等定义来标识它*/



proxy =

dbus_g_proxy_new_for_name

(connection,

“org.freedesktop.Notifications”


/* service */


,

“/”


/*


path */


,





“org.freedesktop.DBus.Introspectable”




/* interface,可以使用宏定义DBUS_INTERFACE_INTROSPECTABLE */


);

error = NULL;


/* 采用同步方式,第二个参数是method,第三个参数是error,后面是不定长的参数,显示输入,后为输出,以G_TYPE_INVALID标识接收,每个参数由GType类型和存贮参数值的地址构成。在这个例子中,输入没有参数,输入有一个参数,是string*/


if(

!

dbus_g_proxy_call

(proxy,”Introspect”,&error, G_TYPE_INVALID,G_TYPE_STRING, &string, G_TYPE_INVALID)

){

if(error->domain == DBUS_GERROR && error->code == DBUS_GERROR_REMOTE_EXCEPTION)

g_printerr(“Caught remote method exception %s:%s”,dbus_g_error_get_name(error),error->message);

else

g_printerr(“Error : %s/n”, error->message);

g_error_free(error);

exit (1);

}

g_print(“Message Method return from bus:/n%s/n”,string);

g_free(string);

g_object_unref(proxy);

return 0;

}


异步的例子

异步中,程序将不等返回消息,继续执行,等有返回消息的时候,触发一个回调函数 。下面是同样的操作,但是用异步的方式来实现:


/*  Test for invoke method asynchronously */


#include <stdio.h>

#include <stdlib.h>

#include <dbus/dbus-glib.h>



static GMainLoop * main_loop;


/* 下面是回调函数,收到method return消息触发函数 */

static void my_callback_func (DBusGProxy       *proxy, DBusGProxyCall   *call_id,  void  *user_data)

{

GError * error = NULL;

gchar * string = NULL;


/* 结束一个消息的收发,处理收到的消息,获取返回值或者error信息 */




dbus_g_proxy_end_call

(proxy,call_id,&error,G_TYPE_STRING,&string,G_TYPE_INVALID);


if(error != NULL){

g_print(“Error in method call : %s/n”, error->message);

g_error_free(error);

}else{

g_print(“SUCCESS,it is now %s/n”,string);

}



g_main_loop_quit(main_loop);



}

int main( int argc , char ** argv)

{

GError * error = NULL;

DBusGConnection * connection;

DBusGProxy    * proxy;



g_type_init();


main_loop = g_main_loop_new(NULL,TRUE);


connection = dbus_g_bus_get (DBUS_BUS_SESSION, & error);


if(connection == NULL){

g_printerr (“Failed to open connection to bus : %s/n”,

error->message);

g_error_free( error);

exit( 1 );

}


/* Create a proxy object for the ‘bus driver’ named org.freedesktop.DBus */


proxy =

dbus_g_proxy_new_for_name

(connection, “org.freedesktop.Notifications”,  “/”,                                 DBUS_INTERFACE_INTROSPECTABLE);


/* 异步触发,也可以带上一个超时的时间限制,使用

dbus_g_proxy_call_with_timeout

。这里的参数只需带上输入的情况。第四个参数为携带到回调函数的user_data,第五个参数标识释放user_data的函数,例如g_free等*/




dbus_g_proxy_begin_call

(proxy,”Introspect”,my_callback_func, NULL,NULL, G_TYPE_INVALID);


g_main_loop_run(main_loop);

return 0;

}

在上面的例子中,使用了GMainLoop的方式,对于线程D-Bus还提供了

dbus_g_thread_init

来处理。


相关链接:

我的Linux相关文章



版权声明:本文为flowingflying原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。