Вы можете использовать метод, указанный в 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 s(i{ii}i)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;
}
person
Ranjit Katuri
schedule
15.07.2013