2012-01-23 28 views
0

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

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<ustring>对象。使用这个参数化的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将数据存入我自己的缓冲区?我想尽可能保证类型安全。

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

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

回答

0

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

而不是调用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<ustring>这样的:

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

看来工作。