capnproto-rust icon indicating copy to clipboard operation
capnproto-rust copied to clipboard

[RPC] add way to get a self-reference from within a method call

Open dwrensha opened this issue 7 years ago • 1 comments

capnproto-c++ has thisCap.

I imagine we could achieve something similar by adding a get_self() -> Client method to ParamsHook and Params.

dwrensha avatar Feb 22 '18 01:02 dwrensha

I spent a bit of time on this. My objective was to add a method get_self(&self) -> my_module::Client, on Params, where Client is actually a typed Client generated from the capnp tool.

Unfortunately, that solution doesn't work well with structs having generics. Let's analyze this interface from test.capnp:

interface Interface(Qux) {
  call @0 Inner2(Text) -> (qux :Qux, gen :TestGenerics(TestAllTypes, TestAnyPointer));
  otherCall @1 Inner2(List(Text)) -> Inner2(List(Int16));
}

The generated client takes 3 generics: pub struct Client<Foo,Bar,Qux>, but the generated method parameters only take the generics they actually need, as pub type CallParams<Bar,Foo,> (notice it doesn't have Qux).

Now, to return a typed client from CallParams, I would need to associate a Client<Foo,Bar,Qux> to a CallParams<Bar,Foo>, but there's no way I can do that, because Qux is not specified. There are multiple valid Clients for a single CallParams<Bar,Foo>.

Another solution, which doesn't require adding more generics to every generated parameter, is to have a thread local variable CURRENT_THIS, and set it before every method call. Then, the capnp tool can generate a Server::get_client(&mut self) method to retrieve the content of CURRENT_THIS. Considering that the method takes &mut self, the content of CURRENT_THIS will always be correct for the lifetime of self.

ranfdev avatar Nov 21 '23 22:11 ranfdev

Resolved by #595. Now methods have self: Rc<Self>, which can be passed to capnp_rpc::new_client_from_rc().

dwrensha avatar Oct 28 '25 18:10 dwrensha