D-Bus, UDisks и Glibmm привязки - PullRequest
       16

D-Bus, UDisks и Glibmm привязки

0 голосов
/ 23 января 2012

У меня проблема с простой концепцией D-Bus. Я использую привязки D-Bus Glibmm (пространство имен 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), который в основном является: "одна структура массива путей объекта". Из документов я прочитал, что тип «путь к объекту» обрабатывается так же, как и тип «строка», поэтому нетипизированный VariantBase, созданный во время get_child(0), позволяет самому быть преобразованным в Variant<ustring> объект. Используя этот параметризованный вариант, тривиально извлечь строку, используя 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 содержит значение string . Так почему метод call_sync() возвращает объект типа варианта? Я что-то пропустил? Может кто-нибудь сказать мне, как я могу правильно прочитать атрибут NativePath, не используя метод get_data() и не memcpy 'данные в мой собственный буфер? Я хотел бы сделать это как можно более безопасным для типов.

Еще одна вещь. Когда я использую метод data.print(true), я получаю правильное содержимое атрибута NativePath в закодированной форме. Это означает, что движок знает, что это строка . Так почему же он сообщает об этом как о варианте? Это ошибка или особенность? : P

Извините за мой английский, мое замешательство и спасибо за любую помощь.

1 Ответ

0 голосов
/ 24 января 2012

ОК, у меня есть решение: похоже, это ошибка, или, по крайней мере, это логика, которую я не понимаю.

Вместо вызова VariantContainerBase 'get_child(0), собственноМожно вызвать прямую функцию Glib g_variant_get_child(), например, так:

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();

Кажется, что это работает.

...