Future_dbus-glib_plans

This page is for use sketching out possible new directions and extenstions to dbus-glib.

DBusGInterface

DBusGInterface is the base class of all generated dbus GInterfaces.

It has one method, invoke that takes a pointer to a class instance, an interface gtype, an offset into the vtable and varargs (null terminated,with in/out null-separated)

typedef gboolean (*DBusGInvoker)(gpointer instance, GType, GQuark, ...); 

The default implementation is gboolean dbus_g_default_invoker (gpointer instance, GType iface, int function, ...). It peeks the interface on the instance and calls the function at the offset, using the marshaller found by looking up the offset in the interface's qdata. (it can use G_VALUE_COLLECT to collect the varargs for calling the marshaller, out params would all be collected a G_TYPE_POINTER)

Please reconsider. All D-Bus methods should be implemented "asynchronously" on the service side - some methods can only be implemented like this, and for those that return immediately it's trivial to use the "asynchronous" (callback-based) API anyway. See telepathy-glib. --SimonMcVittie

Generated Interfaces

From introspection xml and a text file listing the GTypes for function in and out parameters, we generate GInterfaces.

Each enum, private to the interface implementation, gives an index into the vtable for each function. (e.g DO_ACTION_ID is index for the function pointer for do_action).

The interface's struct contains a normal vtable of function pointers.

Attached as qdata ("DBusGInterfaceInfo") is an opaque struction that contains: the interface type is an array, ordered as the offset enum above, of ordered lists of GTypes, null seperated into in and out types and a marshaller for a function with these in/out types; a map of interface function name (by quark) to offset; a string giving the fully scoped dbus interface name that this GInterface implements. (e.g. org.freedesktop.Foo.Bar)

In base_init, this map is initialised from static data (where gtypes and function names are in string form)

The interface function definitions are all of the form:

gboolean maman_ibaz_do_action (MamanIbaz *self, foo in1, in2, in3, ... out1, out2.....) 
{ 
  DBusGInvoker invoker = 
    (DBusGInvoker*) g_dataset_id_get_data(self, 
       g_quark_from_static_string ("DBusGInvoker")); 

  if (!invoker) invoker = dbus_g_default_invoker; 

  return invoker(maman_ibaz_get_type(), 
                 DO_ACTION_ID, 
                 in1, in2, in3..., NULL, 
                 out1, out, out3 ...., NULL); 
}

D-Bus client side

GType dbus_g_remote_factory_create_type (DBusGConnection*, gchar* bus_name, gchar* object_path, GType first_interface_gtype, ...) 

is called to create a remote object type, that inherits from DBusGRemote and implements the interfaces passed in. The invoke method in DBusGInterface is filled with dbus_g_remote_invoker that uses the qdata on the interface type to look up the gtypes to marshal and send a message. Busname and path come from the base DBusGRemote.

I oppose any API that does not encourage asynchronous calls. How would this API do asynchronous calls at all? --SimonMcVittie

Possible other helper functions

typedef void (*DBusGCreatedRemote)(DBusGRemote* new_remote); bool dbus_g_remote_factory_introspect_and_create (DBusGConnection*, gchar* bus_name, gchar* object_path, DBusGCreatedRemote* new_remote_cb ) 

Using DBusGInterface on server side

When coding objects to be exported on the bus, you can inherit from an interface as defined above. When the object has been attached to a connection/path by dbus_g_connection_register_g_object, any incoming method calls to that path can look up the interfaces for your object, using the qdata to choose which interface to call on, it can then look up the function name. It demarshals the message to the gtypes it finds for that function and uses the offset to call into the interface's vtable using the marshaller.