4

I'm learning how to play with this g_variant_new() and it's really confusing me. I've read the https://developer.gnome.org/glib/unstable/glib-GVariant.html#g-variant-new but I can't understand it easily.

I have a code:

#define MM_DBUS_SERVICE "org.freedesktop.ModemManager1"
#define MM_DBUS_PATH "/org/freedesktop/ModemManager1/Modem/0"
#define MM_DBUS_GET_PROPERTIES  "org.freedesktop.DBus.Properties"
....

int i;
    GError *error = NULL;
    GVariant *ret;
    char **paths;
    ret = g_dbus_proxy_call_sync (proxy,
                          "org.freedesktop.DBus.Properties.Get",
                          g_variant_new ("(ss)",
                                      "org.freedesktop.ModemManager1.Modem",
                                      "SignalQuality"),
                          G_DBUS_CALL_FLAGS_NONE, -1,
                          NULL, &error);

    if (!ret) {
            g_dbus_error_strip_remote_error (error);
            g_print ("failed: %s\n", error->message);
            g_error_free (error);
            return;
    }

    g_variant_get (ret, "(v)", &paths);
    g_variant_unref (ret);

    for (i = 0; paths[i]; i++) {
            g_print ("Printing \n");
            g_print ("%s\n", paths[i]);
    }
    g_strfreev (paths);

It compiles fine but when it runs I get seg_fault. TESTING Printing

Printing Segmentation fault

The result I am expecting from this call is:

dbus-send --system --print-reply --dest=org.freedesktop.ModemManager1 "/org/freedesktop/ModemManager1/Modem/0" org.freedesktop.DBus.Properties.Get string:org.freedesktop.ModemManager1.Modem string:"SignalQuality"

method return sender=:1.1 -> dest=:1.121 reply_serial=2
   variant       struct {
       uint32 38
       boolean true
   }

How do I get the variant data structure and the data in it out of the call? How am I supposed to form the g_variant_new() call to accomplish this?

Thanks

parsley72
  • 8,449
  • 8
  • 65
  • 98
Arn
  • 600
  • 1
  • 6
  • 22

1 Answers1

5

I think, first you need to deconstruct tuple with:

GVariant *inner;
g_variant_get (ret, "(v)", &inner);

And then decompose a tuple with:

guint32 num;
gboolean b;

g_variant_get (inner, "(ub)", &num, &b);

Check this

You can also use functions g_variant_get_type_string(parameters) and g_variant_is_of_type (parameters, G_VARIANT_TYPE (type_string)). The first is good for debugging and finding out the data format, i.e. format string, the second is preventive measure if DBus API is changed in the future and instead of crash you can generate meaningful g_warning() and take actions (e.g. return some error from function).

pmod
  • 10,450
  • 1
  • 37
  • 50
  • Thanks!! I still get this: (process:4434): GLib-CRITICAL **: `ub' is not a valid GVariant format string (process:4434): GLib-CRITICAL **: g_variant_get: assertion `valid_format_string (format_string, TRUE, value)' failed Segmentation fault – Arn Mar 24 '16 at 23:02
  • @Ali Hmm, can you print then g_variant_get_type_string(inner) ? – pmod Mar 24 '16 at 23:12
  • Hmmm yes I added the brackets already...but i still get....(process:4565): GLib-CRITICAL **: g_variant_get_va: assertion `value != NULL' failed – Arn Mar 24 '16 at 23:22
  • yes I've already done the gboolean correction too but still error :-) – Arn Mar 24 '16 at 23:32
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/107284/discussion-between-ali-and-pmod). – Arn Mar 24 '16 at 23:42
  • @Ali as I wrote you in the chat, I tested this on similar dbus interface and it works correctly – pmod Mar 31 '16 at 22:28