【问题标题】:D-Bus how to create and send a Dict?D-Bus如何创建和发送一个Dict?
【发布时间】:2015-07-10 11:53:06
【问题描述】:

我有一个向 DBus 公开方法的过程,其中一个参数采用以下类型签名a{sv}

{String, Variant} 的字典

The libDBus documentation for dbus_message_append_args 未能为此提供足够的参考。 specification under container-types中出现了一些信息,具体来说:

DICT_ENTRY 的工作方式与结构完全相同,但不是括号 它使用花括号,并且有更多限制。限制条件 是:它仅作为数组元素类型出现;它正好有两个 花括号内的单个完整类型;第一首单曲 完整类型(“键”)必须是基本类型而不是容器 类型。实现不得接受数组之外的 dict 条目, 不得接受具有零个、一个或两个以上字段的 dict 条目, 并且不能接受带有非基本类型键的 dict 条目。一个字典 entry 始终是一个键值对。


在尝试附加字典时,我收到以下错误消息:

type dict_entry isn't supported yet in dbus_message_append_args_valist

虽然我实际上使用的是dbus_message_append_args(我猜错误消息有些不对劲)。

dbus_message_append_args() 有另外两种替代方法:

dbus_message_iter_append_basic()dbus_message_iter_append_fixed_array()

虽然我可以使用以下内容创建一个空的 Dict 容器:

  const char * container_d_sig = "{sv}";
  DBusMessageIter iter, sub;
  dbus_message_iter_init_append(msg, &iter);
  dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, container_d_sig, &sub);
  dbus_message_iter_close_container(&iter, &sub);

这两种追加方法似乎都不支持添加结构。不知道在这里尝试什么...

【问题讨论】:

    标签: c ipc dbus


    【解决方案1】:

    首先,关于 D-Bus 库:您在几个地方都谈到了 dbus-glib,但您提到的函数不是 dbus-glib 的一部分,而是 libdbus。如果你还在努力寻找使用 D-Bus 的最佳方式,我建议你忘记这两个:libdbus 是非常低级的(它的文档甚至以 开头“如果你直接使用这个低级 API,您正在注册一些痛苦”)并且不推荐使用 dbus-glib。目前最好的 D-Bus API 是 GDBus,它是 GLib GIO 的一部分:它比其他两个 API 设计得更好,经过良好测试和支持。

    现在,至于实际问题,dbus_message_append_args() 的文档确实说得很清楚:

    要附加可变长度的基本类型或任何更复杂的值,您 必须使用迭代器而不是这个函数。

    换句话说,您应该使用dbus_message_iter_open_container() 来准备迭代器,直到它指向您可以使用dbus_message_iter_append_basic() 的地方。请注意,在您的示例中,字典是一个容器,字典条目是一个容器,而变体是一个容器......换句话说,它很快就会变得非常复杂。如果您真的想这样做,请查看例如Connman 示例代码。

    正如我所提到的,理智的路线是 GDBus。创建更复杂的签名非常容易,因为您可以使用 GVariantBuilder API:

    GVariantBuilder builder;
    g_variant_builder_init (&builder, G_VARIANT_TYPE("a{sv}"));
    g_variant_builder_add (&builder, "{sv}", "name1", my_variant);
    
    /* Now use the builder results with g_dbus_connection_call()
       or g_dbus_proxy_call() */
    

    【讨论】:

    • 谢谢,我更新了我的问题。你是说我可以通过多次dbus_message_iter_append_basic() 调用来模拟添加结构吗?低级 api 的原因也是我希望它在没有 GIO 依赖项的情况下工作。
    • 字典条目是 DBUS_TYPE_DICT_ENTRY 类型的容器。您使用迭代器打开它,附加内容,然后关闭容器。关于 GLib/GIO 依赖关系:我无法想象避免 Glib(当它提供您想要的 API 时)是明智选择的情况。成本真的很低,但它非常有用。甚至官方的 D-Bus 教程也同意我的观点:“D-Bus 的推荐 GLib API 是 GDBus。”
    • 您能否将您所描述的作为代码添加到您的答案中?我未能获得正确的行为 - 并且文档没有提供示例。
    • 抱歉,我想我并没有那么投入...自从我不得不使用 libdbus 已经有好几年了,现在我不会再回去了,因为存在更好的选择。但是看看我链接到的 Connman 代码:它质量很高,并且它们使用的方法签名足够复杂,可以显示很多不同的东西。
    【解决方案2】:

    我知道这个问题是不久前提出的,但最近我有一个非常相似的问题,经过几个小时的反复试验,这是我想出的一些代码,它对我有用。希望它可以帮助其他人...

    DBusMessage* testMessage()
    {
        DBusMessage* mssg = dbus_message_new_signal("/fi/w1/wpa_supplicant1/Interfaces/0", "fi.w1.wpa_supplicant1.Interface", "PropertiesChanged");
    
        DBusMessageIter iter, aIter;
        dbus_message_iter_init_append(mssg, &iter);
        if (!dbus_message_iter_open_container(&iter, 'a', "{sv}", &aIter))
            return nullptr;
    
        DBusMessageIter eIter;
        if (!dbus_message_iter_open_container(&aIter, 'e', NULL, &eIter)) {
            dbus_message_iter_abandon_container_if_open(&iter, &aIter);
            return nullptr;
        }
    
        const char* key = "test key";
        dbus_message_iter_append_basic(&eIter, 's', static_cast<void*>(&key));
    
        DBusMessageIter vIter;
        if (!dbus_message_iter_open_container(&eIter, 'v', "i", &vIter)) {
            dbus_message_iter_abandon_container_if_open(&aIter, &eIter);
            dbus_message_iter_abandon_container_if_open(&iter, &aIter);
            return nullptr;
        }
    
        dbus_int32_t val = 42;
        dbus_message_iter_append_basic(&vIter, 'i', static_cast<void*>(&val));
    
        dbus_message_iter_close_container(&eIter, &vIter);
        dbus_message_iter_close_container(&aIter, &eIter);
        dbus_message_iter_close_container(&iter, &aIter);
    
        return mssg;
    }
    

    这是 C++,但应该很容易适应 C。返回的消息具有 a{sv} 的签名。 The dbus docs 很有帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-01-16
      • 2018-01-15
      • 1970-01-01
      • 2021-11-28
      • 2013-05-20
      • 1970-01-01
      • 2015-08-17
      • 2020-06-30
      相关资源
      最近更新 更多