Ruby D-Bus Tutorial - Creating a Service
This chapter deals with the opposite side of the basic client usage, namely the creation of a D-Bus service. It contains the following sections:
Registering a service
Now that you know how to perform D-Bus calls, and how to wait for and handle signals, you might want to learn how to publish some object and interface to provide them to the D-Bus world. Here is how you do that.
As you should already know, D-Bus clients that provide some object to be called remotely are services. Here is how to allocate a name on a bus:
bus = DBus.session_bus service = bus.request_service(“org.ruby.service”)Now this client is know to the outside world as org.ruby.service
.
Note that this is a request and it can be denied! When it
is denied, an exception (DBus::NameRequestError
) is thrown.
Exporting an object
Now, let’s define a class that we want to export:
class Test < DBus::Object- Create an interface. dbus_interface “org.ruby.SampleInterface” do
- Create a hello method in that interface. dbus_method :hello, “in name:s, in name2:s” do |name, name2| puts “hello(#{name}, #{name2})” end end end
As you can see, we define a Test
class in which we define a
org.ruby.SampleInterface
interface. In this interface, we define a
method. The given code block is the method’s implementation. This will be
executed when remote programs performs a D-Bus call. Now the annoying part:
the actual method definition. As you can guess the call
creates a hello
method that takes two parameters both of type string.
The :s means “of type string”. Let’s have a look at some other common
parameter types:
- u means unsigned integer
- i means integer
- y means byte
- (ui) means a structure having a unsigned integer and a signed one.
- a means array, so that “ai” means array of integers
- as means array of string
- a(is) means array of structures, each having an integer and a string.
For a full description of the available D-Bus types, please refer to the D-Bus specification.
Now that the class has been defined, we can instantiate an object and export it as follows:
exported_obj = Test.new(“/org/ruby/MyInstance”) service.export(exported_obj)This piece of code above instantiates a Test
object with a D-Bus object
path. This object is reachable from the outside world after
service.export(exported_obj)
is called.
Using the exported object
Now, let’s consider another program that will access our newly created service:
ruby_service = bus.service(“org.ruby.service”) obj = ruby_service.object(“/org/ruby/MyInstance”) obj.introspect obj.default_iface = “org.ruby.SampleInterface” obj.hello(“giligiligiligili”, “haaaaaaa”)As you can see, the object we defined earlier is automatically introspectable. See also Basic Client Usage.
Emitting a signal
Let’s add some example method so you can see how to return a value to the caller and let’s also define another example interface that has a signal.
class Test2 < DBus::Object- Create an interface dbus_interface “org.ruby.SampleInterface” do
- Create a hello method in the interface: dbus_method :hello, “in name:s, in name2:s” do |name, name2| puts “hello(#{name}, #{name2})” end
- Define a signal in the interface: dbus_signal :SomethingJustHappened, “toto:s, tutu:u” end
Triggering the signal is a easy as calling a method, but then this time on a local (exported) object and not on a remote/proxy object:
exported_obj.SomethingJustHappened(“blah”, 1)Note that the ThatsALongMethodNameIThink
method is returning a single
value to the caller. Notice that you always have to return an array. If
you want to return multiple values, just have an array with multiple
values.