How to set interface dynamically using zbus

I don't want to use annotations,as below:

use zbus::{Connection, Result, Proxy};

/*#[proxy(
    interface = "org.zbus.BroadcastReceiver",
    default_service = "org.zbus.BroadcastReceiver",
    default_path = "/org/zbus/BroadcastReceiver"
)]*/
trait BroadcastReceiver{
    async fn register(&self, name: &str) -> Result<String>;
}

#[tokio::main]
async fn main() -> Result<()> {
    let connection = Connection::session().await?;

    // `proxy` macro creates `MyGreaterProxy` based on `Notifications` trait.
    //let proxy = BroadcastReceiverProxy::new(&connection).await?;
    //let reply = proxy.register("drop-frame-event").await?;
 
    let p = Proxy::new(
            &connection,
            "org.zbus.BroadcastReceiver",
            "org/zbus/BroadcastReceiver",
            "org.zbus.BroadcastReceiver",
            ).await? ;
    let name:String = p.call("register",&("drop-frame-event",)).await?;
    Ok(())
}

This code will report an error : " Error: Variant(Message("invalid value: character o, expected /")", anyone know what happen?

Documentation and error message suggests the third argument should be "/org/zbus/BroadcastReceiver", not "org/zbus/BroadcastReceiver".

1 Like
use zbus::{Connection, Result, Proxy};

/*#[proxy(
   interface = "org.zbus.BroadcastReceiver",
   default_service = "org.zbus.BroadcastReceiver",
   default_path = "/org/zbus/BroadcastReceiver"
)]*/
trait BroadcastReceiver{
   async fn register(&self, name: &str) -> Result<String>;
}

#[tokio::main]
async fn main() -> Result<()> {
   let connection = Connection::session().await?;

   // `proxy` macro creates `MyGreaterProxy` based on `Notifications` trait.
   //let proxy = BroadcastReceiverProxy::new(&connection).await?;
   //let reply = proxy.register("drop-frame-event").await?;
   
   let p = Proxy::new(
           &connection,
           "org.zbus.BroadcastReceiver",
           "/org/zbus/BroadcastReceiver",
           "org.zbus.BroadcastReceiver",
           ).await? ;
   let name:String = p.call("register",&("drop-frame-event")).await?;


   Ok(())
}

it still show an error after changed to /org/zbus/BroadcastReceiver , like this: Error: MethodError(OwnedErrorName("org.freedesktop.DBus.Error.UnknownMethod"), Some("Unknown method 'register'"), Msg { type: Error, sender: UniqueName(":1.146"), reply-serial: 2, body: Signature("s"), fds: })

the server code :

use std::{error::Error, future::pending};
use zbus::{connection, interface};

struct BroadcastReceiver;

#[interface(name = "org.zbus.BroadcastReceiver")]
impl BroadcastReceiver {
    // Can be `async` as well.
    fn register(&mut self, name: &str) -> String {
        
        println!("name {}",name);
        format!("received {} ", name)
    }
}

// Although we use `async-std` here, you can use any async runtime of choice.
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    let receiver = BroadcastReceiver;
    let _conn = connection::Builder::session()?
        .name("org.zbus.BroadcastReceiver")?
        .serve_at("/org/zbus/BroadcastReceiver", receiver)?
        .build()
        .await?;

    // Do other things or go to wait forever
    pending::<()>().await;

    Ok(())
}

Thanks for your reply! I have found the root cause. This zbus is very incredible. Method names must start with uppercase letters. For example, if written as register, the method cannot be found, but if written as Register, it can be found

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.