2013-06-26 60 views
4

我遇到的問題是特別使用低級API在C中打印出dbus方法調用的響應。我是C的libdbus的新手,但在python-dbus上做了一些工作。打印出Dbus方法調用的響應C

  • 我知道該怎麼寫DBUS方法和方法調用的Python以及在CLI
  • 我可以在互聯網上找到的代碼來調用dbus的方法,但它們不返回或打印出來的響應
  • 我一直在看libdbus doxygen api,但無法確定如何提取響應。

我有我的代碼設置方式,python dbus守護進程運行我想調用的方法。其中一些返回一個字符串。我想要一個C程序連接到會話總線,調用方法,打印出答覆並退出。

這是我目前:

#include <stdio.h> 
#include <dbus/dbus.h> 

static void send_dbus_message (DBusConnection *connection, const char *msg) 
{ 
DBusMessage *message; 
//initialize the message 
message = dbus_message_new_signal ("/org/example/foo/bar", 
            "org.example.foo.bar", 
            msg); 

//send the message 
dbus_connection_send (connection, message, NULL); 
//deallocate the message 
dbus_message_unref (message); 
} 

int main (int argc, char **argv) 
{ 
DBusConnection *connection; 
DBusError error; 

//init error message 
dbus_error_init (&error); 
connection = dbus_bus_get (DBUS_BUS_SESSION, &error); 
if (!connection) 
{ 
    printf ("Connection to D-BUS daemon failed: %s", error.message); 

    //deallocate error message 
    dbus_error_free (&error); 
    return 1; 
} 

send_dbus_message (connection, "HelloWorld"); 
return 0; 
} 

可以同步或異步的。

+0

你看着這些[從實例教程](http://dbus.freedesktop.org/doc/dbus-tutorial.html#glib-more-examples)? – user4815162342

+0

感謝您的回覆,但該示例基於Glib,我試圖避免,因爲我正在寫一個沒有X功能的系統。 – NuclearPeon

+0

我看了下面的網站:http://www.matthew.ath.cx/misc/dbus ......它確實有一些有用的代碼,但它仍然沒有打印出答覆後運行其「調用方法「部分。代碼本身沒有param變量,所以如果你複製/粘貼到c文件並編譯它,它就會失敗。即使有變量,它也不會打印出任何東西。 – NuclearPeon

回答

6

您可以使用http://www.matthew.ath.cx/misc/dbus中提到的方法獲取方法回覆消息。

一旦你有一個dbus消息,你可以使用下面的方法來提取數據。 要解析dbus消息,您需要參數迭代器。啓動它以讀取傳入消息的內容。

DBusMessageIter MsgIter; 
dbus_message_iter_init(msg, &MsgIter);//msg is pointer to dbus message received 

在讀取消息之前,您必須驗證傳入消息的簽名。或者你也可以通過參數驗證去爭論。例如,如果參數類型爲字符串

if (DBUS_TYPE_STRING == dbus_message_iter_get_arg_type(&MsgIter)){ 
    char* str = NULL; 
    dbus_message_iter_get_basic(&MsgIter, &str);//this function is used to read basic dbus types like int, string etc. 
} 

對於複雜的類型,如結構,數組,變體和字典條目,則必須創建對應的子迭代器來分析每個復元素的內容。說,對於秒的DBUS簽名(I {} II我)U,提取是如下

//Parsing a signature s(i{ii}i)u 
DBusMessageIter rootIter; 
dbus_message_iter_init(msg, &rootIter); 

if (DBUS_TYPE_STRING == dbus_message_iter_get_arg_type(&rootIter)) 
{ 
    char* str = NULL; 
    dbus_message_iter_get_basic(&rootIter, &str);//this function is used to read basic dbus types like int, string etc. 
    dbus_message_iter_next(&rootIter);//Go to next argument of root iter 

    //Block to enter and read structure 
    if (DBUS_TYPE_STRUCT == dbus_message_iter_get_arg_type(&rootIter)) 
    { 
    DBusMessageIter structIter; 
    dbus_message_iter_recurse(&rootIter, &structIter);//Initialize iterator for struct 

    //Argument 1 is int32 
    if (DBUS_TYPE_INT32 == dbus_message_iter_get_arg_type(&structIter)) 
    { 
     int a; 
      dbus_message_iter_get_basic(&structIter, &a);//Read integer 
     dbus_message_iter_next(&structIter);//Go to next argument of structiter 

     if (DDBUS_TYPE_DICT_ENTRY == dbus_message_iter_get_arg_type(&structIter)) 
     { 
      DBusMessageIter dictIter;   
       dbus_message_iter_recurse(&structIter, &dictIter);//Initialize iterator for dictentry 
      if (DBUS_TYPE_INT32 == dbus_message_iter_get_arg_type(&dictIter)) 
      { 
      dbus_message_iter_get_basic(&dictIter, &a);//Read integer 
      dbus_message_iter_next(&dictIter);//Go to next argument of dictentry 
      if (DBUS_TYPE_INT32 == dbus_message_iter_get_arg_type(&dictIter)) 
      { 
       dbus_message_iter_get_basic(&dictIter, &a);//Read integer 
      } 
      } 
     } 
     dbus_message_iter_next(&structIter);//Go to next argument of structiter 
      if (DBUS_TYPE_INT32 == dbus_message_iter_get_arg_type(&structIter)) 
     { 
      dbus_message_iter_get_basic(&structIter, &a);//Read integer 
     } 
     } 
    } 
    dbus_message_iter_next(&rootIter);//Go to next argument of root iterator 
    if (DBUS_TYPE_UINT32 == dbus_message_iter_get_arg_type(&rootIter)) 
    { 
    uint32_t b; 
    dbus_message_iter_get_basic(&rootIter, &b);//Read integer 
    } 
} 

完成。在上面的代碼中,我使用的參數簽名檢查參數。相反,您可以使用 dbus_message_iter_get_signature進行一次性驗證。有關更多信息,請參閱libdbus api。

從您的回覆我明白,你有問題,建立連接, 這裏是一個完整的例子,其中一個方法調用服務器上調用,並將結果打印 如果第一個參數是一個字符串。

#include <stdio.h> 
#include <stdlib.h> 
#include <dbus/dbus.h> 
#include <assert.h> 

DBusConnection* conn = NULL; 

//Helper function to setup connection 
void vsetupconnection(); 

//Send method call, Returns NULL on failure, else pointer to reply 
DBusMessage* sendMethodCall(const char* objectpath, \ 
     const char* busname, \ 
     const char* interfacename, \ 
     const char* methodname); 

#define TEST_BUS_NAME    "org.freedesktop.DBus" 
#define TEST_OBJ_PATH    "/org/freedesktop/DBus" 
#define TEST_INTERFACE_NAME   "org.freedesktop.DBus.Introspectable" 
#define TEST_METHOD_NAME   "Introspect" 

int main (int argc, char **argv) 
{ 
    vsetupconnection(); 

    DBusMessage* reply = sendMethodCall(TEST_OBJ_PATH, TEST_BUS_NAME, TEST_INTERFACE_NAME, TEST_METHOD_NAME); 
    if(reply != NULL) { 

     DBusMessageIter MsgIter; 
     dbus_message_iter_init(reply, &MsgIter);//msg is pointer to dbus message received 

     if (DBUS_TYPE_STRING == dbus_message_iter_get_arg_type(&MsgIter)){ 
      char* str = NULL; 
      dbus_message_iter_get_basic(&MsgIter, &str); 
      printf("Received string: \n %s \n",str); 
     } 

     dbus_message_unref(reply);//unref reply 
    } 
    dbus_connection_close(conn); 
    return 0; 
} 

void vsetupconnection() 
{ 
    DBusError err; 
    // initialise the errors 
    dbus_error_init(&err); 
    // connect to session bus 
    conn = dbus_bus_get(DBUS_BUS_SESSION, &err); 
    if (dbus_error_is_set(&err)) { 
     printf("Connection Error (%s)\n", err.message); 
     dbus_error_free(&err); 
    } 
    if (NULL == conn) { 
     exit(1); 
    } 
    else { 
     printf("Connected to session bus\n"); 
    } 
} 

DBusMessage* sendMethodCall(const char* objectpath, const char* busname, const char* interfacename, const char* methodname) 
{ 
    assert(objectpath != NULL); assert(busname != NULL); assert(interfacename != NULL); 
    assert(methodname != NULL); assert(conn != NULL); 

    DBusMessage* methodcall = dbus_message_new_method_call(busname,objectpath, interfacename, methodname); 

    if (methodcall == NULL) { 
     printf("Cannot allocate DBus message!\n"); 
    } 
    //Now do a sync call 
    DBusPendingCall* pending; 
    DBusMessage* reply; 

    if (!dbus_connection_send_with_reply(conn, methodcall, &pending, -1))//Send and expect reply using pending call object 
    { 
     printf("failed to send message!\n"); 
    } 
    dbus_connection_flush(conn); 
    dbus_message_unref(methodcall); 
    methodcall = NULL; 

    dbus_pending_call_block(pending);//Now block on the pending call 
    reply = dbus_pending_call_steal_reply(pending);//Get the reply message from the queue 
    dbus_pending_call_unref(pending);//Free pending call handle 
    assert(reply != NULL); 

    if(dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) { 
     printf("Error : %s",dbus_message_get_error_name(reply)); 
      dbus_message_unref(reply); 
      reply = NULL; 
    } 

    return reply; 
} 
+0

感謝您的帖子,但我不認爲它觸及我的問題。首先,你引用了我在我的評論中提到的同一個鏈接@ user4815162342,我一直沒有成功。 打印出答覆是我所追求的。 我會經歷並測試您在寫作時所寫的內容,但在回覆中沒有看到任何打印消息,因此我不認爲它正在回答我的問題。 你也正在初始化'char str',但它沒有在你的代碼中被引用。 – NuclearPeon

+0

我認爲你面臨着從DBusMessage中提取參數的問題。用測試代碼更新答案以供參考。 –