-
Notifications
You must be signed in to change notification settings - Fork 143
Expand file tree
/
Copy pathserver_cr.rs
More file actions
73 lines (58 loc) · 3.52 KB
/
Copy pathserver_cr.rs
File metadata and controls
73 lines (58 loc) · 3.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
/*
This example is a WIP demo of the "Crossroads" module, successor of the "Tree" module.
This example creates a D-Bus server with the following functionality:
It registers the "com.example.dbustest" name, creates a "/hello" object path,
which has an "com.example.dbustest" interface.
The interface has a "Hello" method (which takes no arguments and returns a string),
and a "HelloHappened" signal (with a string argument) which is sent every time
someone calls the "Hello" method.
When you run this example, you can test it with this command:
dbus-send --print-reply --dest=com.example.dbustest /hello com.example.dbustest.Hello string:MyName
You should see output like this:
method return time=1667227809.834235 sender=:1.1620 -> destination=:1.1628 serial=7 reply_serial=2
string "Hello MyName! This API has been used 3 times."
*/
use dbus::blocking::Connection;
use dbus_crossroads::{Crossroads, Context};
use std::error::Error;
// This is our "Hello" object that we are going to store inside the crossroads instance.
struct Hello { called_count: u32 }
fn main() -> Result<(), Box<dyn Error>> {
// Let's start by starting up a connection to the session bus and request a name.
let c = Connection::new_session()?;
c.request_name("com.example.dbustest", false, true, false)?;
// Create a new crossroads instance.
// The instance is configured so that introspection and properties interfaces
// are added by default on object path additions.
let mut cr = Crossroads::new();
// Let's build a new interface, which can be used for "Hello" objects.
let iface_token = cr.register("com.example.dbustest", |b| {
// This row advertises (when introspected) that we can send a HelloHappened signal.
// We use the single-tuple to say that we have one single argument, named "sender" of type "String".
// The msg_fn returns a boxed function, which when called constructs the message to be emitted.
let hello_happened = b.signal::<(String,), _>("HelloHappened", ("sender",)).msg_fn();
// Let's add a method to the interface. We have the method name, followed by
// names of input and output arguments (used for introspection). The closure then controls
// the types of these arguments. The last argument to the closure is a tuple of the input arguments.
b.method("Hello", ("name",), ("reply",), move |ctx: &mut Context, hello: &mut Hello, (name,): (String,)| {
// And here's what happens when the method is called.
println!("Incoming hello call from {}!", name);
hello.called_count += 1;
let reply = format!("Hello {}! This API has been used {} times.", name, hello.called_count);
// Now call the function we got earlier to get a signal message.
// The function takes all its arguments as the second parameter, so we must again
// tuple our single argument into a single-tuple.
let signal_msg = hello_happened(ctx.path(), &(name,));
// The ctx parameter can be used to conveniently send extra messages.
ctx.push_msg(signal_msg);
// And the return value from the method call is a tuple of the output arguments.
Ok((reply,))
});
});
// Let's add the "/hello" path, which implements the com.example.dbustest interface,
// to the crossroads instance.
cr.insert("/hello", &[iface_token], Hello { called_count: 0});
// Serve clients forever.
cr.serve(&c)?;
unreachable!()
}