hp at redhat.com
Fri May 28 13:51:27 PDT 2004
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
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,
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
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
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. ;-)
More information about the dbus