低级DBus C API主循环

时间:2017-08-25 15:36:50

标签: c linux dbus low-level-io freedesktop.org

当尝试使用回调函数进行DBus回复时,我无法创建一个良好/良好工作的主循环。

我想做的很简单,进行DBus调用并指定一个应该在回复时调用的函数。这是因为在计算并到达答复之前,我不想一直阻止我的线程。

我首先使用dbus_connection_send_with_reply(..)来获取DBusPendingCall,然后使用dbus_pending_call_set_notify(..)指定回调函数。在这之前,当连接到总线时,我已经启动了另一个应该等待响应并调用回调函数的线程。我没有找到任何示例,也没有很好的文档说明我应该如何设计这样的dbus主循环。我试过了:

// Main dbus loop handling data transfer and callbacks..
void *dbus_main(void *args)
{
    my_dbus dbus = (my_dbus)args;

    while (MY_DBUS_STATUS_STOPPING != dbus->status
            && dbus_connection_read_write_dispatch(dbus->conn, -1))
        ;

    return 0;
}

// Start the dbus main loop in a new thread
void dbus_main_start(my_dbus dbus) {
    if (!pthread_create(&dbus->th, NULL, dbus_main, dbus)) {
        // PRINT ERROR
    }
}

我的问题是两件事:

  • 我尝试通过将dbus->状态标志设置为MY_DBUS_STATUS_STOPPING并等待线程加入来停止应用。如果线程在dbus_connection_read_write_dispatch(..)函数中被阻塞,则这不起作用。如果我希望应用程序快速停止,那么我需要指定一个非常短的超时。我不能以其他方式唤醒被阻止的线程吗?

  • 更严重的是,使用此代码我不会从我调用的方法中获得任何回调。如果我添加一些fprintf(..)来写入stdout我可能会突然得到我的回调。它看起来很随意,所以也许是某种僵局?我尝试在发送消息和使用_set_notify(..)函数添加回调之间使用dbus_connection_flush(..)。没有任何区别......但是在同一个地方向stdout打印一些字母可以解决问题。在dbus-main-loop中打印到标准输出空的“;”似乎有时会做这个伎俩......

所以任何人都有一个使用低级别dbus api和异步方法的例子,即不使用_block(..)??

2 个答案:

答案 0 :(得分:0)

高度建议您使用D-Bus库其他而不是libdbus,因为正如您所发现的那样,libdbus很难正确使用。如果可能,请使用GDBusQtDBus,因为它们是更高级别的绑定,更易于使用。如果您需要较低级别的绑定,sd-bus比libdbus更现代。

如果您使用GDBus,则可以使用GMainLoop来实现主循环。如果您使用sd-bus,则可以使用sd-event

答案 1 :(得分:0)

您可以按如下方式创建一个简单的DBus应用程序......

要设置服务器来处理传入消息,请调用dbus_connection_register_object_path传入包含函数指针的VTable来处理消息。如:

{ .unregister_function = UnregisteredMessage, .message_function = ServiceMessage }

要发送新消息,请拨打dbus_connection_send_with_reply然后dbus_pending_call_set_notify以关联回调函数以处理回复。

接下来,您将需要为DBus提供服务。这可以在一个单独的线程中完成,也可以在同一个线程中定期调用非阻塞调用,如下所示:

/* Non-blocking read of the next available message */
dbus_connection_read_write ( MyDBusConnection, 0 ) ;

while ( dbus_connection_get_dispatch_status ( MyDBusConnection ) == DBUS_DISPATCH_DATA_REMAINS )
{
   dbus_connection_dispatch ( MyDBusConnection ) ;
}

这里有一些使用DBUS C API的好例子:http://www.matthew.ath.cx/misc/dbus