从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_ | 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).oall: $(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相关文章