about signals

Havoc Pennington hp at redhat.com
Fri May 28 13:51:27 PDT 2004


Hi,

Cool, I'll take a stab at explaining how I think bindings should work. I
think I've done this in archives too but probably mixed in with a lot of
other noise.

There are two halves to a binding: using a remote object, and
implementing an object to be used remotely.

A. Using a remote object should involve the following:

     1. Create a proxy for the remote object. The proxy constructor may
        have multiple overloads depending on the situation. For the
        message bus case, it would typically take a service name, an
        object path, and an interface.
     2. Methods and signals should then work on the proxy in the same
        way they would for a local object, except that they can throw
        exceptions related to remote access. Signal connections should
        work as they normally would in the language or system you're
        binding to: just connect your handler/slot to your signal.
     3. When the remote object dies it should be signaled in some way,
        the best way to do this is probably binding-specific. For
        example with GObject we want to emit the destroy signal.
     4. Destroying the proxy should not destroy the remote object. There
        may be many proxies for one remote object; there's no pretense
        that the proxy "is" the remote object.
     5. For this reason, using the term "proxy" is encouraged.

B. Implementing an object to be used remotely should mean:

     1. Write a normal object in your language or system.
     2. Have a call DBus::Connection::register_object(object_path,
        object_instance)
     3. The binding should then automatically route incoming method
        calls to the registered object, invoke the object's
        corresponding method, and build a reply message from the
        method's return values
     4. The binding should automatically generate a signal message each
        time the object emits a signal
     5. Probably you want to allow explicit "make this signal remote"
        and "make this method local-only" override tags on methods and
        signals. Methods are remote by default (since it's zero-cost)
        and signals are local-only by default (to avoid spamming the bus
        with silly signals)
     6. When an object is destroyed it should be automatically
        unregistered
     7. The binding should automatically implement the Introspect()
        method for all registered objects.

In summary on the "client" side you build a proxy object and use it as a
normal object, and for the "server" you build an object instance and
register it, and via introspection the object is automatically exported
remotely.

For Qt, the introspection data for the "server" side is of course
available from QObject and generated via moc.

For the proxy on the "client" side you would either need to generate the
proxy statically, or use an untypesafe approach as in DBusGProxy. If you
generate the proxy statically I would recommend that the
statically-generated code be a thin typesafe wrapper around an
untypesafe generic proxy, because this makes the code a lot smaller and
if you make the untypesafe interface public it allows app developers to
do things dynamically if they want.

To be honest I have no idea how close the existing Python, Mono, and Qt
bindings are to this description. ;-)

Havoc





More information about the dbus mailing list