Skype and DBus: should my client library act as a server?
julienjpk at email.com
Wed Mar 18 13:00:12 PDT 2015
Since I just succeeded in writing a basic program to reach Skype
properly (through a not-so-proper API on its side), I thought I'd bring
an answer to Simon McVittie's previous email, for completeness let's say.
> This is also poor D-Bus API design, particularly if they do not document
> that this is how it works; but again, if you're using Skype, you're
> stuck with their choice of API.
Even I who discovered DBus recently, I can see how impractical this
design is, and how very little of DBus' features it actually takes
advantage. However I like to consider myself a rather realistic person,
and anyone who dares hope for any improvement or change on the Skype
API's side is undoubtedly dreaming awake.
>> If so, would any of you have some pointers as to how I can register
>> objects and their methods using the low-level API?
> * Don't. High-level APIs are there for a reason. I would suggest
> exporting a high-level object using gdbus-codegen, or at least the
> semi-high-level GDBusInterfaceSkeleton (which is what the code generated
> by gdbus-codegen uses).
> * For C or C++ without Qt, prefer GDBus (a reimplementation) over
> libdbus. You can still use the low-level APIs that in GDBus - libdbus
> only has semi-low-level and really-low-level message-passing-based APIs,
> whereas GDBus has both a message-passing layer equivalent to libdbus,
> and higher-level object-oriented layers on top of that.
I'm afraid I had misunderstood the notion of "low-level API" in the case
of DBus. To me, libdbus as a whole is a low-level API, whether you go as
far as reading the "D-Bus secret internal implementation details" or
not. Setting watch functions, polling watch descriptors, and registering
objects with dbus_connection_register_object_path() are, to me, all
"low-level" operations, no matter whether or not I use
DBusWatch/DBusTimeout, or bother myself with manual processing of the
incoming queue. For this reason, I designed my first test program this way:
- Connect to the bus, check Skype's availability.
- Register the client object so that Skype can reach me.
- Set my watch functions (at least add/remove).
- Start sending my requests from another thread.
- Use select() to wait for incoming method calls from Skype. When it
happens, use dbus_watch_handle() and dbus_connection_dispatch() to
retrieve the call, and have it processed by my object's message handler.
I made sure access to the connection was secured by a mutex, and
everything seems to work fine. It might have been more clever to detach
the "event" part on a thread, instead of the "sending" part, but that's
not really an issue here. To me, this simple setup is "low-level".
However, reading the rest of your email...
> * g_dbus_connection_register_object() (or its slightly lower-level
> libdbus equivalent dbus_connection_register_object_path()) is the
> canonical semi-low-level way to register objects to receive method calls.
> * If you insist on torturing yourself with low-level details, use
> g_dbus_connection_add_filter() or dbus_connection_add_filter() to filter
> incoming method calls, reply to them, and mark them as "I handled this"
> so that the library does not send back a redundant error reply.
... it seems that there is an even lower-level which I hadn't
considered, and don't intend to use (then I'd say my test program was
"semi-low-level"). I tried using filters just to "see what it did", and
while I do find it handy, I don't need that kind of "early processing"
of my incoming method calls anyway.
> I hope you are aware of the cognitive dissonance involved in reading an
> introduction to the basics, and then doing things that the D-Bus
> maintainer specifically advises against :-)
I am, I am, and actually, if I had to release code, I would probably
abandon libdbus, and rely on GDBus (maybe even the high-level part of
the API). As it so happens, Linux Skype relies on Qt, which in turn
relies on GLib: I wouldn't even have any kind of dependency concern,
since Skype has to be installed in order for the program/library to be
usable, anyway :)
I was trying to write a simple "emitter/receiver" program, to lay the
groundwork for some more significant development, and to understand the
basics of DBus programming on the way. Based on your email, I began by
writing a small GDBus program (which worked on first try), and went back
to libdbus afterwards to reproduce the same thing. The advantage of GLib
here is the immediate double-threaded context: all you have to do is set
a handler, and everything goes into place asynchronously without too
much effort. However, it seemed to me like GLib was overkill for what I
was trying to achieve at the moment (it is, after all, a huge library...).
Thank you very much for your input!
Julien Kritter (PGP key 0xC3075A58)
julienjpk at email.com
More information about the dbus