打印出 C 中 Dbus 方法调用的响应
Posted
技术标签:
【中文标题】打印出 C 中 Dbus 方法调用的响应【英文标题】:Print out response of Dbus Method Call in C 【发布时间】:2013-06-24 04:03:37 【问题描述】:我遇到的问题是使用低级 API 专门打印出 C 中 dbus 方法调用的响应。我是 C 的 libdbus 新手,但在 python-dbus 中做了一些工作。
我知道如何在 python 和 CLI 中编写 dbus 方法和方法调用 我可以在 Internet 上找到调用 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;
可以是同步的或异步的。
【问题讨论】:
你看过这些examples from the tutorial吗? 感谢您的回复,但该示例基于 Glib,这是我在为没有 X 功能的系统编写时试图避免的。 我查看了以下站点:matthew.ath.cx/misc/dbus ... 确实有一些有用的代码,但在运行他们的“调用方法”部分后仍然没有打印出回复。代码本身没有参数变量,因此如果将其复制/粘贴到 c 文件中并编译它会失败。即使有变量,它也不会打印出任何东西。 你在另一端有什么东西可以响应 /org/example/foo/bar/org.example.foo.bar 信号吗?此外,您发送的信号是一种方式。虽然在协议级别上可以回复信号(您可以发送回消息并将 replySerial 设置为信号的串行),但如果使用的话,这并不是很常见。 【参考方案1】:您可以使用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.
对于复杂类型,如结构、数组、变体和字典条目,您必须创建相应的子迭代器来解析每个复杂元素的内容。比如说,对于 s(iiii)u 的 dbus 签名,提取如下所示
//Parsing a signature s(iiii)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;
【讨论】:
感谢您的帖子,但我认为这与我的问题无关。首先,您参考了我在 cmets 中提到的指向 @user4815162342 的相同链接,我已经完成了该链接,但没有成功。打印出回复是我所追求的。当我有时间时,我会检查并测试你写的内容,但我在你的回复中没有看到任何打印信息,所以我认为它没有回答我的问题。你也在初始化char str
,但它没有在你的代码中被引用。以上是关于打印出 C 中 Dbus 方法调用的响应的主要内容,如果未能解决你的问题,请参考以下文章