You can use the method mentioned at http://www.matthew.ath.cx/misc/dbus to get the method response.
Once you get the dbus message, you can use the following method to retrieve the data. To parse a dbus message, you need an argument iterator. Initialize it to read the contents of the incoming message.
DBusMessageIter MsgIter; dbus_message_iter_init(msg, &MsgIter);//msg is pointer to dbus message received
Before reading, you must verify the signature of the incoming message. Or you can also use an argument by checking the arguments. For example, if the argument type is a string
if (DBUS_TYPE_STRING == dbus_message_iter_get_arg_type(&MsgIter)){ char* str = NULL; dbus_message_iter_get_basic(&MsgIter, &str);
For complex types, such as structures, arrays, options, and dict entries, you need to create appropriate child iterators to parse the contents of each complex element. Say for a dbus signature s (i {ii} i) u, extraction is performed as below
//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 } }
In the above code, I used an argument by checking the signature of the arguments. Instead, you can do a one-time check using dbus_message_iter_get_signature . For more information see the Libdbus api.
#
From your answer, I understand that you have problems setting up the connection, here is a complete example when a method call is called on the server, and the result is printed if the first argument is a string.
#
#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; }