D-Bus、UDisks 和 Glibmm 的绑定

Posted

技术标签:

【中文标题】D-Bus、UDisks 和 Glibmm 的绑定【英文标题】:D-Bus, UDisks and Glibmm's bindings 【发布时间】:2012-02-17 03:31:04 【问题描述】:

我对简单的 D-Bus 概念有疑问。我正在使用 Glibmm D-Bus 绑定(Gio::DBus 命名空间)来访问 UDisks 接口。我想读取系统上找到的每个硬盘的一些属性,所以首先我需要枚举 UDisks 报告的所有磁盘,如下所示:

Glib::RefPtr<Gio::DBus::Connection> bus;

int main() 
    using namespace Glib;
    using namespace Gio;

    Glib::init();
    Gio::init();

    bus = DBus::Connection::get_sync(Gio::DBus::BUS_TYPE_SYSTEM);
    RefPtr<DBus::Proxy> udisks_proxy = DBus::Proxy::create_sync(bus, "org.freedesktop.UDisks", "/org/freedesktop/UDisks", "org.freedesktop.UDisks");

    VariantContainerBase devices_variant = udisks_proxy->call_sync("EnumerateDevices");
    VariantIter iterator(devices_variant.get_child(0));

    Variant<ustring> var;
    while(iterator.next_value(var)) 
        ustring name = var.get();

        LOG("device: '%s", name.c_str());
        process_device(name);
    

    return 0;

这似乎工作正常,因为call_sync() 返回一个VariantContainerBase,其中包含(ao) 对象,基本上是:“对象路径数组的一个结构”。从文档中我读到“对象路径”类型的处理方式与“字符串”类型的处理方式相同,这就是为什么在get_child(0) 期间创建的无类型VariantBase 允许将自身转换为Variant&lt;ustring&gt; 对象。使用这个参数化的 Variant,使用var.get() 提取字符串很简单。

然后我尝试使用此方法从每个驱动器的属性中读取一些内容(在本例中为 NativePath 属性):

void process_device(const Glib::ustring& objpath) 
    using namespace Glib;
    using namespace Gio;

    RefPtr<DBus::Proxy> attrs = DBus::Proxy::create_sync(bus, "org.freedesktop.UDisks", objpath, "org.freedesktop.DBus.Properties");

    std::vector<VariantBase> args;
    args.push_back(Variant<ustring>::create(objpath));
    args.push_back(Variant<ustring>::create("NativePath"));
    VariantContainerBase data = attrs->call_sync("Get", VariantContainerBase::create_tuple(args));

    LOG("return type: %s", data.get_type_string().c_str());

问题在于VariantContainerBase 对象包含(v) 签名。这意味着该对象是“变体”,所以我不能将它转换为任何东西。

属性的自省显示NativePath 拥有一个字符串 值。那么为什么call_sync() 方法会返回一个变体类型的对象呢?我错过了什么吗?谁能告诉我,我怎样才能正确读取NativePath 属性,而不使用get_data() 方法和memcpy'ing 数据到我自己的缓冲区?我想尽可能保证类型安全。

还有一件事。当我使用data.print(true) 方法时,我以编码形式获得NativePath 属性的正确内容。这意味着引擎知道这是一个字符串。那么为什么它将它报告为变体呢?它是错误还是功能? :P

对不起我的英语,我的困惑,感谢您的帮助。

【问题讨论】:

【参考方案1】:

好的,我有解决方案:这似乎是一个错误,或者至少这是一个我不明白的逻辑。

不调用VariantContainerBaseget_child(0),正确的方法是直接调用Glib函数g_variant_get_child(),比如f.e.这个:

GVariant *output;
g_variant_get_child(data.gobj(), 0, "v", & output);

它将正确地将output 的变体类型设置为v 内部的类型(在我的情况下,它将output 的类型设置为s)。在此之后,当您获取s 类型的远程数据时,您可以将其转换为Variant&lt;ustring&gt;,如下所示:

Variant<Glib::ustring> item(output);
Glib::ustring text = item.get();

它似乎有效。

【讨论】:

以上是关于D-Bus、UDisks 和 Glibmm 的绑定的主要内容,如果未能解决你的问题,请参考以下文章

D-Bus GLib 绑定​​——无法让代码脱离实际

如何确定使用哪个 D-Bus 绑定

glibmm.h:找不到这样的目录或文件

python udisks - 枚举设备信息

UDisks2 的 Dbus 自省不完整?

使用 GDBus 通过 D-Bus 发送字节数组(类型为 `ay`)