我們繼續(xù)學(xué)習(xí)D-Bus,參考http://dbus./doc/dbus/libdbus-tutorial.html ,相關(guān)的API接口reference參考http://dbus./doc/dbus/api/html/modules.html 。從底層,即libdbus學(xué)習(xí)如何發(fā)送Method以及如何等待應(yīng)答,在上上次學(xué)習(xí)中,給出了同步的方式 ,這是更為高層的處理方式,建議使用。監(jiān)聽(tīng)method和監(jiān)聽(tīng)signal的方式非常相似。在給出例子之前,我希望和上次學(xué)習(xí)一樣給出一個(gè)示意圖,更好地了解D-Bus的各個(gè)概念。
監(jiān)聽(tīng)Method call消息,并返回Method reply消息 Method的監(jiān)聽(tīng)和signal的監(jiān)聽(tīng)的處理時(shí)一樣,但是信號(hào)是不需要答復(fù),而Method需要。在下面的例子中,我們將學(xué)習(xí)如何在消息中加入多個(gè)參數(shù)(在D-Bus學(xué)習(xí)(四)中,我們加入了一個(gè)參數(shù))的情況。 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <dbus/dbus-glib.h> #include <dbus/dbus.h> #include <unistd.h>
/*讀取消息的參數(shù),并且返回兩個(gè)參數(shù),一個(gè)是bool值stat,一個(gè)是整數(shù)level*/ void reply_to_method_call(DBusMessage * msg, DBusConnection * conn){ DBusMessage * reply; DBusMessageIter arg; char * param = NULL; dbus_bool_t stat = TRUE; dbus_uint32_t level = 2010; dbus_uint32_t serial = 0; //從msg中讀取參數(shù),這個(gè)在上一次學(xué)習(xí)中學(xué)過(guò) if(!dbus_message_iter_init(msg,&arg)) printf("Message has no args/n"); else if(dbus_message_iter_get_arg_type(&arg) != DBUS_TYPE_STRING) printf("Arg is not string!/n"); else dbus_message_iter_get_basic(&arg,& param); if(param == NULL) return; //創(chuàng)建返回消息reply reply = dbus_message_new_method_return(msg); //在返回消息中填入兩個(gè)參數(shù),和信號(hào)加入?yún)?shù)的方式是一樣的。這次我們將加入兩個(gè)參數(shù)。 dbus_message_iter_init_append(reply,&arg); if(!dbus_message_iter_append_basic (&arg,DBUS_TYPE_BOOLEAN,&stat)){ printf("Out of Memory!/n"); exit(1); } if(!dbus_message_iter_append_basic (&arg,DBUS_TYPE_UINT32,&level)){ printf("Out of Memory!/n"); exit(1); } //發(fā)送返回消息 if( !dbus_connection_send (conn, reply, &serial)){ printf("Out of Memory/n"); exit(1); } dbus_connection_flush (conn); dbus_message_unref (reply); }
/* 監(jiān)聽(tīng)D-Bus消息,我們?cè)谏洗蔚睦又羞M(jìn)行修改 */ void listen_dbus() { DBusMessage * msg; DBusMessageIter arg; DBusConnection * connection; DBusError err; int ret; char * sigvalue;
dbus_error_init(&err); //創(chuàng)建于session D-Bus的連接 connection = dbus_bus_get(DBUS_BUS_SESSION, &err); if(dbus_error_is_set(&err)){ fprintf(stderr,"Connection Error %s/n",err.message); dbus_error_free(&err); } if(connection == NULL) return; //設(shè)置一個(gè)BUS name:test.wei.dest ret = dbus_bus_request_name(connection,"test.wei.dest",DBUS_NAME_FLAG_REPLACE_EXISTING,&err); if(dbus_error_is_set(&err)){ fprintf(stderr,"Name Error %s/n",err.message); dbus_error_free(&err); } if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) return;
//要求監(jiān)聽(tīng)某個(gè)singal:來(lái)自接口test.signal.Type的信號(hào) dbus_bus_add_match(connection,"type='signal',interface='test.signal.Type'",&err); dbus_connection_flush(connection); if(dbus_error_is_set(&err)){ fprintf(stderr,"Match Error %s/n",err.message); dbus_error_free(&err); }
while(true){ dbus_connection_read_write (connection,0); msg = dbus_connection_pop_message (connection);
if(msg == NULL){ sleep(1); continue; }
if(dbus_message_is_signal(msg,"test.signal.Type","Test")){ if(!dbus_message_iter_init(msg,&arg)) fprintf(stderr,"Message Has no Param"); else if(dbus_message_iter_get_arg_type(&arg) != DBUS_TYPE_STRING) g_printerr("Param is not string"); else dbus_message_iter_get_basic(&arg,&sigvalue); }else if(dbus_message_is_method_call(msg,"test.method.Type","Method")){ //我們這里面先比較了接口名字和方法名字,實(shí)際上應(yīng)當(dāng)現(xiàn)比較路徑 if(strcmp(dbus_message_get_path (msg),"/test/method/Object") == TRUE) reply_to_method_call(msg, connection); } dbus_message_unref(msg); } } int main( int argc , char ** argv){ listen_dbus(); return 0; }
發(fā)送Method call消息,并等待Method reply消息 下面的例子在上次學(xué)習(xí)信號(hào)發(fā)送的例子上進(jìn)行修改。如下: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <dbus/dbus-glib.h> #include <dbus/dbus.h> #include <unistd.h> //建立與session D-Bus daemo的連接,并設(shè)定連接的名字,相關(guān)的代碼已經(jīng)多次使用過(guò)了 DBusConnection * connect_dbus(){ DBusError err; DBusConnection * connection; int ret;
//Step 1: connecting session bus /* initialise the erroes */ dbus_error_init(&err); /* Connect to Bus*/ connection = dbus_bus_get(DBUS_BUS_SESSION, &err); if(dbus_error_is_set(&err)){ fprintf(stderr,"Connection Err : %s/n",err.message); dbus_error_free(&err); } if(connection == NULL) return NULL;
//step 2: 設(shè)置BUS name,也即連接的名字。 ret = dbus_bus_request_name(connection,"test.wei.source",DBUS_NAME_FLAG_REPLACE_EXISTING,&err); if(dbus_error_is_set(&err)){ fprintf(stderr,"Name Err : %s/n",err.message); dbus_error_free(&err); } if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) return NULL;
return connection; }
void send_a_method_call(DBusConnection * connection,char * param) { DBusError err; DBusMessage * msg; DBusMessageIter arg; DBusPendingCall * pending; dbus_bool_t * stat; dbus_uint32_t * level; dbus_error_init(&err);
//針對(duì)目的地地址,請(qǐng)參考圖,創(chuàng)建一個(gè)method call消息。 Constructs a new message to invoke a method on a remote object. msg = dbus_message_new_method_call ("test.wei.dest","/test/method/Object","test.method.Type","Method"); if(msg == NULL){ g_printerr("Message NULL"); return; }
//為消息添加參數(shù)。Append arguments dbus_message_iter_init_append(msg, &arg); if(!dbus_message_iter_append_basic (&arg, DBUS_TYPE_STRING,¶m)){ g_printerr("Out of Memory!"); exit(1); }
//發(fā)送消息并獲得reply的handle 。Queues a message to send, as with dbus_connection_send() , but also returns a DBusPendingCallused to receive a reply to the message. if(!dbus_connection_send_with_reply (connection, msg,&pending, -1)){ g_printerr("Out of Memory!"); exit(1); }
if(pending == NULL){ g_printerr("Pending Call NULL: connection is disconnected "); dbus_message_unref(msg); return; }
dbus_connection_flush(connection); dbus_message_unref(msg); //waiting a reply,在發(fā)送的時(shí)候,已經(jīng)獲取了method reply的handle,類(lèi)型為DBusPendingCall。 // block until we recieve a reply, Block until the pending call is completed. dbus_pending_call_block (pending); // get the reply message,Gets the reply, or returns NULL if none has been received yet. msg = dbus_pending_call_steal_reply (pending); if (msg == NULL) { fprintf(stderr, "Reply Null/n"); exit(1); } // free the pending message handle dbus_pending_call_unref(pending); // read the parameters if (!dbus_message_iter_init(msg, &arg)) fprintf(stderr, "Message has no arguments!/n"); else if ( db us_message_iter_get_arg_type (&arg) != DBUS_TYPE_BOOLEAN) fprintf(stderr, "Argument is not boolean!/n"); else dbus_message_iter_get_basic (&arg, &stat); if (!dbus_message_iter_next(&arg)) fprintf(stderr, "Message has too few arguments!/n"); else if ( db us_message_iter_get_arg_type (&arg) != DBUS_TYPE_UINT32 ) fprintf(stderr, "Argument is not int!/n"); else dbus_message_iter_get_basic (&arg, &level);
printf("Got Reply: %d, %d/n", stat, level); dbus_message_unref(msg); }
int main( int argc , char ** argv){ DBusConnection * connection; connection = connect_dbus(); if(connection == NULL) return -1;
send_a_method_call(connection,"Hello, D-Bus"); return 0; }
|