OCT
8
2006

QtRuby DBus progress

This week I've been converting the QtDBus examples from Qt 4.2 to Ruby, and getting the various Qt::DBus* classes working. Now QDBus support is pretty much complete and it will be fun hacking up some interesting apps like bridges to web services like I tried with DCOP. I'll have to get kde4 kdelibs and whatever else builds so I've got some sample apps with DBus support to experiment with.

I just need to find out what QDBusVariants are about and how custom type marshalling/de-marshalling should work in Ruby. Also I haven't done Ruby equivalents to qdbusxml2cpp and qdbuscpp2xml yet as I'm not sure if they're needed. I don't see how it is easier to write code in XML than Ruby. Qt::DBusAbstractAdaptor works fine in QtRuby, but again I'm not sure if it makes sense to use it. Really this stuff needs trying out to see what is useful and what is not. I think it's important for Ruby DBus programming to be as simple as possible.

Here's an example of what the code looks like - this is from the qdbu/listnames example. First the app checks whether it can connect to the session bus:

if !Qt::DBusConnection.sessionBus.connected?
    $stderr.puts("Cannot connect to the D-BUS session bus.\n" \
                 "To start it, run:\n" \
                 "\teval `dbus-launch --auto-syntax`\n")
    exit 1
end

Next it calls the ListNames method to get a list of dbus services from the Qt::DBusMessage instance that is returned:

    bus = Qt::DBusConnection.sessionBus
    dbus_iface = Qt::DBusInterface.new("org.freedesktop.DBus", "/org/freedesktop/DBus", 
                                       "org.freedesktop.DBus", bus)
        
    qDebug(dbus_iface.call("ListNames").arguments[0].to_ruby.inspect)

In QtRuby there is a simpler way to invoke a remote method, you can just do this:

qDebug(dbus_iface.ListNames(arguments.inspect)

You just call the method as if it was local and it will the list of names as a return value. Obviously you can't do error checking without the Qt::DBusMessage, but it is easier and looks prettier.

So QtRuby for Qt4 is looking really nice. But like Alexander says in White vs Black, Good vs Evil I'm a bit annoyed by attempts to ban Ruby apps from the kde modules on the basis of some survey where Ruby scripting got 250 votes, and Python got 300 votes. And I really don't want to have to defend Ruby by bashing Python as that's really lame - there is no reason for it to be an 'either/or' thing.

What advantage will be gained by only having one dynamic language for writing complete apps? Note that the question asked in this survey (with hidden agenda) was 'Preferred Scripting Language' which I would take to mean 'which scripting language to you prefer to use for scripting c++ applications', and I wouldn't take it to mean 'which dynamic language/RAD environment do you prefer to use for writing complete applications'. We are working on KDevelop support and Ruby bindings for KDE4 on the expectation that the killer RAD environment we hope to create can be used to write Ruby kde apps as first class citizens and suitable for inclusion in the kdeedu and other modules. Sorry to sound annoyed, but we don't expect to be banished to only extragear, thankyou very much.

Comments

Ah, come on over to extragear. The water is warm and inviting!

Skype has DBus support I think.


By eean@drupal.org at Mon, 10/09/2006 - 05:22

Skype uses an incompatible, old version of D-Bus. It doesn't work with the current libraries that QtDBus requires. It doesn't work with even the same session daemon.


By Thiago Macieira at Mon, 10/09/2006 - 12:36

QDBusVariant is just a QVariant under another name, so that we can tell whether you want to send a variant or not.

Take these C++ examples:

  iface.call("Method", 1);
  iface.call("Method", QVariant(1));
  iface.call("Method", qVariantFromValue(QDBusVariant(1));

Since the call() method takes QVariants as parameters, the first and second form are exactly the same. So the only way to explicitly specify that you want a variant to be sent (and not an Int32) is to create a QDBusVariant object.

There has been some discussion about dynamic languages and variants among the D-Bus community. The fact that all types are variants in those languages leads to interesting circumstances and corner cases.


By Thiago Macieira at Mon, 10/09/2006 - 12:40

Ah, I see now - thanks for the explanation. I looked at the QDBusVariant code, but it just seemed to wrap a QVariant without really adding anything extra - I get the point now. If you call a proxy in ruby like this:

iface.Method(1)
iface.Method(Qt::Variant.new(1))

The code that converts the list of args to a list of Qt::Variants will know that if there is a Qt::Variant value you want to pass a Variant onto Dbus. I think the problem QDBusVariant solves is C++ specific and they probably won't be needed in QtRuby, as it doesn't have the automatic type coercion to convert a '1' arg to 'QVariant(1)' as in your example.

By the way, at aKademy we discussed how I couldn't get return values for slots (and QtDBus slots) working. It was really obvious in the end. In the array of void *'s passed to qt_metacall, there is a pointer in the zeroth element. And when I set up the return value I was replacing it with another pointer to the return value, instead of just updating what the pointer pointed to with the return value.


By Richard Dale at Mon, 10/09/2006 - 13:37