來自:http://blog.csdn.net/chenyufei1013/article/details/6573411
dbus的是一個低延遲,低開銷,高可用性的IPC機制。通過dbus的daemon,可以實現進程間通信和函數調用。Windows下,dbus的開發庫可以去這裏(http://code.google.com/p/dbus-windows-installer/downloads/list)下載,在VS設置頭文件和lib庫的路徑即可。若是要編寫其Hello World,自然包含客戶端和服務端兩部分。下面的Hello World代碼包含了發送消息和函數調用兩部分,分別描述之。
1) 信號
假設客戶端發送消息,服務端接收。客戶端發送消息的流程如下:
1.創建於dbus daemon的會話連接。
2.創建消息,若有消息參數,附加之(這個一般都有)
3.通過連接發送消息。
1: int main (int argc, char *argv[])
2: {
3: DBusError dberr;
4: DBusConnection *dbconn;
5: DBusMessage *dbmsg;
6: char *text;
7:
8: // 初始話錯誤信息的結構體
9: dbus_error_init (&dberr);
10:
11: // 創建會話連接
12: dbconn = dbus_bus_get (DBUS_BUS_SESSION, &dberr);
13: if (dbus_error_is_set (&dberr)) {
14: fprintf (stderr, "getting session bus failed: %s/n", dberr.message);
15: dbus_error_free (&dberr);
16: return EXIT_FAILURE;
17: }
18:
19: // 創建消息
20: dbmsg = dbus_message_new_signal ("/com/wiley/test",
21: "com.wiley.test",
22: "TestSignal");
23: if (!dbmsg) {
24: fprintf (stderr, "Could not create a new signal/n");
25: return EXIT_FAILURE;
26: }
27:
28: // 消息中,附加文本
29: text = "Hello World";
30: if (!dbus_message_append_args (
31: dbmsg, DBUS_TYPE_STRING, &text, DBUS_TYPE_INVALID)) {
32: fprintf(stderr, "Out Of Memory!/n");
33: return EXIT_FAILURE;
34: }
35:
36: // 發送消息
37: if (!dbus_connection_send (dbconn, dbmsg, NULL)) {
38: fprintf(stderr, "Out Of Memory!/n");
39: return EXIT_FAILURE;
40: }
41: dbus_connection_flush(dbconn);
42:
43: printf ("Sending signal to D-Bus/n");
44:
45: // 釋放消息
46: dbus_message_unref (dbmsg);
47:
48: // 釋放會話連接
49: dbus_connection_unref (dbconn);
50:
51: return EXIT_SUCCESS;
52: }
服務端接收消息的流程如下:
1.創建於dbus daemon的會話連接。
2.爲本次連接設置名稱,客戶端可以通過此名稱進行通信
3.設置消息對應的回調函數
4.添加消息匹配規則
5.進入處理消息的循環
1: static DBusHandlerResult
2: filter_func (DBusConnection *connection,
3: DBusMessage *message,
4: void *user_data)
5: {
6: dbus_bool_t handled = FALSE;
7: char *signal_text = NULL;
8:
9: // 若爲指定信號
10: if (dbus_message_is_signal (message, "com.wiley.test", "TestSignal")) {
11: DBusError dberr;
12: // 初始化錯誤結構體
13: dbus_error_init (&dberr);
14: // 獲取消息的參數
15: dbus_message_get_args (message, &dberr, DBUS_TYPE_STRING, &signal_text, DBUS_TYPE_INVALID);
16: if (dbus_error_is_set (&dberr)) {
17: fprintf (stderr, "Error getting message args: %s", dberr.message);
18: dbus_error_free (&dberr);
19: } else {
20: printf ("Received TestSignal with value of: '%s'/n", signal_text);
21: // 標識本消息已處理
22: handled = TRUE;
23: }
24: }
25: // 返回值決定該消息是否處理
26: return (handled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
27: }
28:
29:
30: int main (int argc, char *argv[])
31: {
32: DBusError dberr;
33: DBusConnection *dbconn;
34:
35: // 初始話錯誤信息的結構體
36: dbus_error_init (&dberr);
37:
38: // 創建會話
39: dbconn = dbus_bus_get (DBUS_BUS_SESSION, &dberr);
40: if (dbus_error_is_set (&dberr)) {
41: fprintf (stderr, "getting session bus failed: %s/n", dberr.message);
42: dbus_error_free (&dberr);
43: return EXIT_FAILURE;
44: }
45:
46: // 向daemon追加了一條路由到該應用程序入口
47: dbus_bus_request_name (dbconn, "com.wiley.test",
48: DBUS_NAME_FLAG_REPLACE_EXISTING, &dberr);
49: if (dbus_error_is_set (&dberr)) {
50: fprintf (stderr, "requesting name failed: %s/n", dberr.message);
51: dbus_error_free (&dberr);
52: return EXIT_FAILURE;
53: }
54:
55: // 設置處理消息的函數
56: if (!dbus_connection_add_filter (dbconn, filter_func, NULL, NULL)) {
57: return EXIT_FAILURE;
58: }
59:
60: // 添加消息匹配規則
61: dbus_bus_add_match (dbconn,
62: "type='signal',interface='com.wiley.test'",
63: &dberr);
64: if (dbus_error_is_set (&dberr)) {
65: fprintf (stderr, "Could not match: %s", dberr.message);
66: dbus_error_free (&dberr);
67: return EXIT_FAILURE;
68: }
69:
70: // 分派消息的Loop
71: while (dbus_connection_read_write_dispatch (dbconn, -1))
72: ; /* empty loop body */
73:
74: return EXIT_SUCCESS;
75: }
2) 跨進程調用
跨進程調用中,客戶端和服務端的流程差不多,假設客戶端跨進程調用服務端函數。
客戶端
1: int main (int argc, char *argv[])
2: {
3: DBusMessage* msg;
4: DBusMessageIter args;
5: DBusConnection* conn;
6: DBusError err;
7: DBusPendingCall* pending;
8: char* param = "no param";
9: int ret;
10: dbus_bool_t stat = FALSE;
11: dbus_uint32_t level = 0;
12:
13: printf("Calling remote method with %s/n", param);
14:
15: // 初始化錯誤
16: dbus_error_init(&err);
17:
18: // 獲取會話連接
19: conn = dbus_bus_get(DBUS_BUS_SESSION, &err);
20: if (dbus_error_is_set(&err)) {
21: fprintf(stderr, "Connection Error (%s)/n", err.message);
22: dbus_error_free(&err);
23: }
24: if (NULL == conn) {
25: exit(1);
26: }
27:
28: // 設置連接名稱,若存在則替換
29: ret = dbus_bus_request_name(conn, "test.method.caller", DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
30: if (dbus_error_is_set(&err)) {
31: fprintf(stderr, "Name Error (%s)/n", err.message);
32: dbus_error_free(&err);
33: }
34: if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
35: exit(1);
36: }
37:
38: // 創建方法調用的消息
39: msg = dbus_message_new_method_call("com.test.dbus.server", // target for the method call
40: "/test/method/Object", // object to call on
41: "test.method.Interface", // interface to call on
42: "Method"); // method name
43: if (NULL == msg) {
44: fprintf(stderr, "Message Null/n");
45: exit(1);
46: }
47:
48: // 附加參數
49: dbus_message_iter_init_append(msg, &args);
50: if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, ¶m)) {
51: fprintf(stderr, "Out Of Memory!/n");
52: exit(1);
53: }
54:
55: // 發送消息(-1表示使用默認超時)
56: if (!dbus_connection_send_with_reply (conn, msg, &pending, -1)) {
57: fprintf(stderr, "Out Of Memory!/n");
58: exit(1);
59: }
60: if (NULL == pending) {
61: fprintf(stderr, "Pending Call Null/n");
62: exit(1);
63: }
64:
65: // 阻塞直到發送的消息隊列爲空
66: dbus_connection_flush(conn);
67:
68: printf("Request Sent/n");
69:
70: // 釋放消息
71: dbus_message_unref(msg);
72:
73: // 阻塞至消息返回
74: dbus_pending_call_block(pending);
75:
76: // 獲取返回消息
77: msg = dbus_pending_call_steal_reply(pending);
78: if (NULL == msg) {
79: fprintf(stderr, "Reply Null/n");
80: exit(1);
81: }
82:
83: // 釋放pending
84: dbus_pending_call_unref(pending);
85:
86: // 讀取參數
87: if (!dbus_message_iter_init(msg, &args))
88: fprintf(stderr, "Message has no arguments!/n");
89: else if (DBUS_TYPE_BOOLEAN != dbus_message_iter_get_arg_type(&args))
90: fprintf(stderr, "Argument is not boolean!/n");
91: else
92: dbus_message_iter_get_basic(&args, &stat);
93:
94: if (!dbus_message_iter_next(&args))
95: fprintf(stderr, "Message has too few arguments!/n");
96: else if (DBUS_TYPE_UINT32 != dbus_message_iter_get_arg_type(&args))
97: fprintf(stderr, "Argument is not int!/n");
98: else
99: dbus_message_iter_get_basic(&args, &level);
100:
101: printf("Got Reply: %d, %d/n", stat, level);
102:
103: // 釋放方法返回的消息
104: dbus_message_unref(msg);
105:
106: return EXIT_SUCCESS;
107: }
服務端
1: static
2: void reply_to_method_call(DBusMessage* msg, DBusConnection* conn)
3: {
4: DBusMessage* reply;
5: DBusMessageIter args;
6: dbus_bool_t stat = TRUE;
7: dbus_uint32_t level = 21614;
8: dbus_uint32_t serial = 0;
9: char* param = "";
10:
11: // 讀取參數
12: if (!dbus_message_iter_init(msg, &args)) // 獲取參數
13: fprintf(stderr, "Message has no arguments!/n");
14: else if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&args)) // 參數類型不爲字符串
15: fprintf(stderr, "Argument is not string!/n");
16: else { // 參數爲字符串
17: dbus_message_iter_get_basic(&args, ¶m);
18: }
19:
20: printf("Method called with %s/n", param);
21:
22: // 創建返回類型的消息,對應於調用的消息
23: reply = dbus_message_new_method_return(msg);
24:
25: // 初始化返回的參數
26: dbus_message_iter_init_append(reply, &args);
27: if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_BOOLEAN, &stat)) { // 附加基本類型的值到消息中
28: fprintf(stderr, "Out Of Memory!/n");
29: exit(1);
30: }
31: if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_UINT32, &level)) { // 附加基本類型的值到消息中
32: fprintf(stderr, "Out Of Memory!/n");
33: exit(1);
34: }
35:
36: // 發送返回消息
37: if (!dbus_connection_send(conn, reply, &serial)) {
38: fprintf(stderr, "Out Of Memory!/n");
39: exit(1);
40: }
41: dbus_connection_flush(conn);
42:
43: // 釋放方法返回的消息
44: dbus_message_unref(reply);
45: }
46:
47: int main (int argc, char *argv[])
48: {
49: DBusError dberr;
50: DBusConnection * dbconn;
51: DBusMessage * msg;
52: int ret;
53:
54: // 初始話錯誤信息的結構體
55: dbus_error_init (&dberr);
56: // 創建會話
57: dbconn = dbus_bus_get (DBUS_BUS_SESSION, &dberr);
58: if (dbus_error_is_set (&dberr)) {
59: fprintf (stderr, "getting session bus failed: %s/n", dberr.message);
60: dbus_error_free (&dberr);
61: return EXIT_FAILURE;
62: }
63:
64: // 爲本次連接設置名稱,客戶端可以通過此名稱進行通信
65: ret = dbus_bus_request_name (dbconn, "com.test.dbus.server",
66: DBUS_NAME_FLAG_REPLACE_EXISTING, &dberr);
67: if (dbus_error_is_set (&dberr)) {
68: fprintf (stderr, "requesting name failed: %s/n", dberr.message);
69: dbus_error_free (&dberr);
70: return EXIT_FAILURE;
71: }
72: if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
73: fprintf(stderr, "Not Primary Owner (%d)/n", ret);
74: exit(1);
75: }
76:
77: // 循環等待消息
78: while (true) {
79: // 非阻塞的獲取下一個消息
80: // TODO: 如何阻塞?
81: dbus_connection_read_write(dbconn, 0);
82:
83: // 獲取消息
84: msg = dbus_connection_pop_message(dbconn);
85: if (NULL == msg) {
86: // sleep(1);
87: continue;
88: }
89:
90: // 相應消息調用
91: if (dbus_message_is_method_call(msg, "test.method.Interface", "Method"))
92: reply_to_method_call(msg, dbconn);
93:
94: // 釋放引用
95: dbus_message_unref(msg);
96: }
97:
98: return EXIT_SUCCESS;
99: }