dbus的hello world

来源:互联网 发布:网络机房用什么灭火器 编辑:程序博客网 时间:2024/05/16 14:56

来自: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, &param)) {
  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, &param);
  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: }
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 宝宝吃饱了就吐吐了在吃怎么办 3岁宝宝吃了就吐怎么办 6岁儿童又吐又拉怎么办 还没满月的宝宝肚子胀气怎么办 婴儿拉屎有粘液像果冻状怎么办 宝宝不爱吃饭怎么办吃就吐出来 19天的宝宝生理性腹泻怎么办 33天的婴儿生理性腹泻怎么办 两个多月宝宝生理性腹泻怎么办 3岁儿童又吐又拉怎么办 宝宝两岁了突然说话有点口吃怎么办 姜文怎么克服口吃 说话结巴怎么办 慢性咽炎嗓子干哑说话费劲怎么办 感冒后嗓子不疼 说话费劲怎么办 小孩子在幼儿园内向老尿裤子怎么办 五岁宝宝总是抽鼻子有黄鼻涕怎么办 2岁宝宝头有大人的那么大怎么办 一岁四个月宝宝不理人不说话怎么办 两岁七个月还不会说话怎么办 2岁3个月宝宝说话结巴怎么办 两周的宝宝突然说话结巴怎么办 宝宝3岁半了说话口吃怎么办? 四十天的宝宝吐奶严重怎么办 宝宝吐奶从鼻子喷出来怎么办 六个多月宝宝吐奶一股酸味怎么办 50天的宝宝吃了就吐怎么办 微信语音群聊超过9人怎么办 四个月宝宝母乳不够不喝奶粉怎么办 四个月的宝宝母乳不够吃怎么办 火山直播十多天了还都是假人怎么办 吉利汽车锁了后屁股灯还亮怎么办 六个月凶了他突然不说话了怎么办 微信聊天聊的时间长了没话题怎么办 群聊同学加我微信不想加怎么办? 翡翠销售遇到不说话的客人怎么办 4个月宝宝吃手上瘾怎么办 宝宝吃手上瘾拒绝吃奶粉吃奶怎么办 2岁宝宝特别粘人爱哭怎么办 3岁半宝宝突然说话口吃怎么办 2岁3个月宝宝突然说话结巴怎么办 一位特爱说话爱玩的高中生怎么办