来自: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: }