您的位置:首页 > 其它

dbus基础--创建dbus客户端与服务端的实例参考

2012-07-03 09:11 357 查看
/*

* Example low-level D-Bus code.

* Written by Matthew Johnson <dbus@matthew.ath.cx>

*

* This code has been released into the Public Domain.

* You may do whatever you like with it.

*/

#include <dbus/dbus.h>

#include <stdbool.h>

#include <unistd.h>

#include <stdio.h>

#include <stdlib.h>

/**

* Connect to the DBUS bus and send a broadcast signal

*/

void sendsignal(char* sigvalue)

{

   DBusMessage* msg;

   DBusMessageIter args;

   DBusConnection* conn;

   DBusError err;

   int ret;

   dbus_uint32_t serial = 0;

   printf("Sending signal with value %s/n", sigvalue);

   // initialise the error value

   dbus_error_init(&err);

   // connect to the DBUS system bus, and check for errors

   conn = 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 (NULL == conn) { 

      exit(1); 

   }

   // register our name on the bus, and check for errors

   ret = dbus_bus_request_name(conn, "test.signal.source", 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 (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) { 

      exit(1);

   }

   // create a signal & check for errors 

   msg = dbus_message_new_signal("/test/signal/Object", // object name of the signal

                                 "test.signal.Type",    // interface name of the signal

                                 "Test");               // name of the signal

   if (NULL == msg) 

   { 

      fprintf(stderr, "Message Null/n"); 

      exit(1); 

   }

   // append arguments onto signal

   dbus_message_iter_init_append(msg, &args);

   if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &sigvalue)) {

      fprintf(stderr, "Out Of Memory!/n"); 

      exit(1);

   }

   // send the message and flush the connection

   if (!dbus_connection_send(conn, msg, &serial)) {

      fprintf(stderr, "Out Of Memory!/n"); 

      exit(1);

   }

   dbus_connection_flush(conn);

   

   printf("Signal Sent/n");

   

   // free the message 

   dbus_message_unref(msg);

}

/**

* Call a method on a remote object

*/

void query(char* param) 

{

   DBusMessage* msg;

   DBusMessageIter args;

   DBusConnection* conn;

   DBusError err;

   DBusPendingCall* pending;

   int ret;

   bool stat;

   dbus_uint32_t level;

   printf("Calling remote method with %s/n", param);

   // initialiset the errors

   dbus_error_init(&err);

   // connect to the system bus and check for errors

   conn = 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 (NULL == conn) { 

      exit(1); 

   }

   // request our name on the bus

   ret = dbus_bus_request_name(conn, "test.method.caller", 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 (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) { 

      exit(1);

   }

   // create a new method call and check for errors

   msg = dbus_message_new_method_call("test.method.server",// target for the method call

                                      "/test/method/Object", // object to call on

                                      "test.method.Type",    // interface to call on

                                      "Method");             // method name

   if (NULL == msg) { 

      fprintf(stderr, "Message Null/n");

      exit(1);

   }

   // append arguments

   dbus_message_iter_init_append(msg, &args);

   if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, ¶m)) {

      fprintf(stderr, "Out Of Memory!/n"); 

      exit(1);

   }

   

   // send message and get a handle for a reply

   if (!dbus_connection_send_with_reply (conn, msg, &pending, -1)) { // -1 is default timeout

      fprintf(stderr, "Out Of Memory!/n"); 

      exit(1);

   }

   if (NULL == pending) { 

      fprintf(stderr, "Pending Call Null/n"); 

      exit(1); 

   }

   dbus_connection_flush(conn);

   

   printf("Request Sent/n");

   

   // free message

   dbus_message_unref(msg);

   

   // block until we recieve a reply

   dbus_pending_call_block(pending);

   // get the reply message

   msg = dbus_pending_call_steal_reply(pending);

   if (NULL == msg) {

      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, &args))

      fprintf(stderr, "Message has no arguments!/n"); 

   else if (DBUS_TYPE_BOOLEAN != dbus_message_iter_get_arg_type(&args)) 

      fprintf(stderr, "Argument is not boolean!/n"); 

   else

      dbus_message_iter_get_basic(&args, &stat);

   if (!dbus_message_iter_next(&args))

      fprintf(stderr, "Message has too few arguments!/n"); 

   else if (DBUS_TYPE_UINT32 != dbus_message_iter_get_arg_type(&args)) 

      fprintf(stderr, "Argument is not int!/n"); 

   else

      dbus_message_iter_get_basic(&args, &level);

   printf("Got Reply: %d, %d/n", stat, level);

   

   // free reply 

   dbus_message_unref(msg);   

}

void reply_to_method_call(DBusMessage* msg, DBusConnection* conn)

{

   DBusMessage* reply;

   DBusMessageIter args;

   bool stat = true;

   dbus_uint32_t level = 21614;

   dbus_uint32_t serial = 0;

   char* param = "";

   // read the arguments

   if (!dbus_message_iter_init(msg, &args))

      fprintf(stderr, "Message has no arguments!/n"); 

   else if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&args)) 

      fprintf(stderr, "Argument is not string!/n"); 

   else 

      dbus_message_iter_get_basic(&args, ¶m);

   printf("Method called with %s/n", param);

   // create a reply from the message

   reply = dbus_message_new_method_return(msg);

   // add the arguments to the reply

   dbus_message_iter_init_append(reply, &args);

   if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_BOOLEAN, &stat)) { 

      fprintf(stderr, "Out Of Memory!/n"); 

      exit(1);

   }

   if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_UINT32, &level)) { 

      fprintf(stderr, "Out Of Memory!/n"); 

      exit(1);

   }

   // send the reply && flush the connection

   if (!dbus_connection_send(conn, reply, &serial)) {

      fprintf(stderr, "Out Of Memory!/n"); 

      exit(1);

   }

   dbus_connection_flush(conn);

   // free the reply

   dbus_message_unref(reply);

}

/**

* Server that exposes a method call and waits for it to be called

*/

void listen() 

{

   DBusMessage* msg;

   DBusMessage* reply;

   DBusMessageIter args;

   DBusConnection* conn;

   DBusError err;

   int ret;

   char* param;

   printf("Listening for method calls/n");

   // initialise the error

   dbus_error_init(&err);

   

   // connect to the bus and check for errors

   conn = 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 (NULL == conn) {

      fprintf(stderr, "Connection Null/n"); 

      exit(1); 

   }

   

   // request our name on the bus and check for errors

   ret = dbus_bus_request_name(conn, "test.method.server", 

                               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 (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) { 

      fprintf(stderr, "Not Primary Owner (%d)/n", ret);

      exit(1); 

   }

   // loop, testing for new messages

   while (true) {

      // non blocking read of the next available message

      dbus_connection_read_write(conn, 0);

      msg = dbus_connection_pop_message(conn);

      // loop again if we haven't got a message

      if (NULL == msg) { 

         sleep(1); 

         continue; 

      }

      

      // check this is a method call for the right interface & method

      if (dbus_message_is_method_call(msg, "test.method.Type", "Method")) 

         reply_to_method_call(msg, conn);

      // free the message

      dbus_message_unref(msg);

   }

}

/**

* Listens for signals on the bus

*/

void receive()

{

   DBusMessage* msg;

   DBusMessageIter args;

   DBusConnection* conn;

   DBusError err;

   int ret;

   char* sigvalue;

   printf("Listening for signals/n");

   // initialise the errors

   dbus_error_init(&err);

   

   // connect to the bus and check for errors

   conn = 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 (NULL == conn) { 

      exit(1);

   }

   

   // request our name on the bus and check for errors

   ret = dbus_bus_request_name(conn, "test.signal.sink", 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 (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {

      exit(1);

   }

   // add a rule for which messages we want to see

   dbus_bus_add_match(conn, "type='signal',interface='test.signal.Type'", &err); // see signals from the given interface

   dbus_connection_flush(conn);

   if (dbus_error_is_set(&err)) { 

      fprintf(stderr, "Match Error (%s)/n", err.message);

      exit(1); 

   }

   printf("Match rule sent/n");

   // loop listening for signals being emmitted

   while (true) {

      // non blocking read of the next available message

      dbus_connection_read_write(conn, 0);

      msg = dbus_connection_pop_message(conn);

      // loop again if we haven't read a message

      if (NULL == msg) { 

         sleep(1);

         continue;

      }

      // check if the message is a signal from the correct interface and with the correct name

      if (dbus_message_is_signal(msg, "test.signal.Type", "Test")) {

         

         // read the parameters

         if (!dbus_message_iter_init(msg, &args))

            fprintf(stderr, "Message Has No Parameters/n");

         else if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&args)) 

            fprintf(stderr, "Argument is not string!/n"); 

         else

            dbus_message_iter_get_basic(&args, &sigvalue);

         

         printf("Got Signal with value %s/n", sigvalue);

      }

      // free the message ,http://blog.csdn.net/shanzhizi

      dbus_message_unref(msg);

   }

}

int main(int argc, char** argv)

{

   if (2 > argc) {

      printf ("Syntax: dbus-example [send|receive|listen|query] [<param>]/n");

      return 1;

   }

   char* param = "no param";

   if (3 >= argc && NULL != argv[2]) param = argv[2];

   if (0 == strcmp(argv[1], "send"))

      sendsignal(param);

   else if (0 == strcmp(argv[1], "receive"))

      receive();

   else if (0 == strcmp(argv[1], "listen"))

      listen();

   else if (0 == strcmp(argv[1], "query"))

      query(param);

   else {

      printf ("Syntax: dbus-example [send|receive|listen|query] [<param>]/n");

      return 1;

   }

   return 0;



编译

----------------------------------------------------------

错误1:

$ gcc test.c

test.c:8:23: 错误: dbus/dbus.h:No such file or directory

......



错误提示,dbus库的头文件位置不正确(如果已经安装了dbus的话)

$ sudo updatedb

$ sudo locate dbus.h (查看dbus.h的所在位置)

/usr/local/include/dbus-1.0/dbus/dbus.h

/usr/include/dbus-1.0/dbus/dbus.h

看来dbus.h的存放位置的确不正确,这可能是由于dbus-1.0的安装位置有问题,没关系,调整一下dbus的头文件位置就可以了(调整方法如下):

root@zxl:/usr/include# ln -sf dbus-1.0/dbus 

错误2:

$ gcc test.c

在包含自 test.c:8 的文件中:

/usr/include/dbus/dbus.h:29:33: 错误: dbus/dbus-arch-deps.h:No such file or directory

......

依然有头文件无法正确定位的问题,从错误提示来看,该文件应该在/usr/include/dbus/目录下,可是进入该目录查看竟然没有,那就在整个系统中查找该文件。

root@zxl:/usr/include/dbus# locate dbus-arch-deps.h

/usr/local/lib/dbus-1.0/include/dbus/dbus-arch-deps.h

/usr/lib/dbus-1.0/include/dbus/dbus-arch-deps.h

将该文件复制到/usr/include/dbus目录下

错误3:

$ gcc test.c

......

test.c:(.text+0xbb6): undefined reference to `dbus_message_iter_get_basic'

test.c:(.text+0xbd4): undefined reference to `dbus_message_unref'

collect2: ld 返回 1

需要连接动态库dbus

$ cd /usr/lib

$ ls *dbus*

libdbus-1.a   libdbus-1.so.3      libdbus-glib-1.so

libdbus-1.la libdbus-1.so.3.2.0 libdbus-glib-1.so.2

libdbus-1.so libdbus-glib-1.a    libdbus-glib-1.so.2.1.0

$ gcc test.c -l dbus-1 -o dbus

执行(用普通用户身份执行)

----------------------------------------------------------

$ ./dbus receive

Listening for signals

Match rule sent

Got Signal with value luoling

$ ./dbus send luoling    (再开一个标签)

Sending signal with value luoling

Signal Sent
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐