From: http://blog.csdn.net/flowingflying/article/details/5418180
從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 來處理。