It works ! Thank you for the expanded explanation, it helped a lot. I initially though there would be a "prettier" out-of-the-box solution, but as long as it works...
While I have you, I have a more general question. Is it common case to distribute Cap'n'Proto genererated headers as part of a library, or everything must stay private ? Let's say I have defined some enum in the .capnp and I want the users of my library to use them. For the moment I have a duplicated the definition of this enum in a public header, and I do static casts before serialization. Le lundi 26 avril 2021 à 17:40:59 UTC+2, [email protected] a écrit : > You need your `SubscriberImpl` to hold a regular C++ pointer back to the > `MediaLibraryImpl` that created it, so that you can access its > `publishers_` set through that pointer. You can pass the pointer to > `SubscriberImpl`'s constructor. > > You'll also want to make sure the pointer doesn't become a dangling > pointer, so `SubscriberImpl` should also hold a `MediaLibrary::Client` > which points to the same `MediaLibraryImpl` -- holding this counts as a > strong reference so Cap'n Proto won't destroy the `MediaLibraryImpl`. > Inside `addSubscriber()` you can use `thisCap()` to get a > `MediaLibrary::Client` pointing to `this`, then you'd pass that to > `SubscriberImpl`'s constructor, along with the plain C++ pointer to `this`. > > -Kenton > > On Mon, Apr 26, 2021 at 10:25 AM Théophile B. <[email protected]> > wrote: > >> Thank you for your quick answer! >> >> The `Server` to `Client` "conversion" is done via the bootstrap >> capability, but I need the underlying `Server` back when calling >> capabilities returned by the bootstrap capability. >> Here is a simplified example where I (tried) to implement your advice: >> >> interface MediaLibrary { >> addPublisher @0 (name :Text) -> (pub :Publisher); >> addSubscriber @1 (name :Text) -> (sub :Subscriber); >> >> interface Publisher {} >> >> interface Subscriber { >> listenTo @0 (publisher :Publisher); >> } >> } >> >> class MediaLibraryImpl final : public MediaLibrary::Server { >> public: >> kj::Promise<void> addPublisher(AddPublisherContext context) override { >> my_underlying_library::Publisher* output = ...; // call the >> underlying lib >> MediaLibrary::Publisher::Client pub = publishers_.add(kj::heap< >> PublisherImpl>(output)); >> context.getResults().setPub(pub); >> return kj::READY_NOW; >> } >> >> kj::Promise<void> addSubscriber(AddSubscriberContext context) override { >> my_underlying_library::Subscriber* output = ...; // call the >> underlying lib >> MediaLibrary::Subscriber::Client sub = subscribers_.add(kj::heap< >> SubscriberImpl>(output)); >> context.getResults().setSub(sub); >> return kj::READY_NOW; >> } >> >> private: >> capnp::CapabilityServerSet<MediaLibrary::Subscriber> subscribers_; >> capnp::CapabilityServerSet<MediaLibrary::Publisher> publishers_; >> }; >> >> class PublisherImpl : public virtual GstDaemon::Publisher::Server { >> protected: >> PublisherImpl(my_underlying_library::Publisher* pub) : pub_(pub) {} >> >> private: >> my_underlying_library::Publisher* pub_; >> } >> >> class SubscriberImpl : public virtual GstDaemon::Subscriber::Server { >> protected: >> SubscriberImpl(my_underlying_library::Subscriber* sub) : sub_(sub) {} >> >> kj::Promise<void> listenTo(ListenToContext context) override { >> auto pub = context.getParams().getPublisher(); // GstDaemon::Publisher >> ::Client >> // No access to CapabilityServerSet ! >> // We we would like to do: sub_->listenTo("pub_") >> } >> >> private: >> my_underlying_library::Subscriber* sub_; >> } >> >> If I understand well, I can now do subscribers_.getLocalServer(" >> GstDaemon::Publisher::Client") from `MediaLibraryImpl`. >> Bu what about SubscriberImpl, where the `listenTo` needs `PublisherImpl` >> ? >> Is it possible to have access to `MediaLibraryImpl` from `SubscriberImpl` >> ? >> Instead, should I pass references to the `CapabilityServerSet` to ` >> PublisherImpl` and `SubscriberImpl` ? >> >> Le lundi 26 avril 2021 à 16:30:55 UTC+2, [email protected] a écrit : >> >>> Hi Théophile, >>> >>> Take a look at CapabilityServerSet: >>> >>> >>> https://github.com/capnproto/capnproto/blob/6b5bcc2c6e954bc6e167ac581eb628e5a462a469/c++/src/capnp/capability.h#L607-L633 >>> >>> When you convert your `Server` object to a `Client`, you need to do it >>> using a CapabilityServerSet. Later, you can use the same set to unwrap the >>> `Client` and get the underlying `Server` back -- even if the client has >>> been passed over the network and back in the meantime. >>> >>> -Kenton >>> >>> On Mon, Apr 26, 2021 at 9:25 AM Théophile B. <[email protected]> >>> wrote: >>> >>>> I'm not sure I'm usign the right terminology in my question, but I hope >>>> you will understand my problem with the following example. >>>> >>>> I'm developing a media library where the user can play/pause/stop >>>> different kinds of "pipelines" (source ~ camera, filter ~ processing, sink >>>> ~ display). Depending on their type, these pipeline can listen to each >>>> other, or not (e.g: a source pipeline cannot listen). I'm now working on a >>>> "capnp wrapper" of the library, so that it can be controlled via RPC. >>>> >>>> I have replicated the class inheritance with success: >>>> >>>> interface Publisher {} >>>> >>>> interface Subscriber { >>>> listenTo @0 (publisher :Publisher); >>>> } >>>> >>>> interface Pipeline { >>>> play @0 (); >>>> pause @1 (); >>>> stop @2 (); >>>> } >>>> >>>> interface SourcePipeline extends(Pipeline, Publisher) {} >>>> >>>> interface FilterPipeline extends(Pipeline, Publisher, Subscriber) {} >>>> >>>> interface SinkPipeline extends(Pipeline, Subscriber) {} >>>> >>>> Server-side I have those impl classes, which holds the references to >>>> the underlying objects of the media library (pub_ & sub_). >>>> >>>> class PublisherImpl : public virtual GstDaemon::Publisher::Server { >>>> protected: >>>> PublisherImpl(my_underlying_library::Publisher* pub) : pub_(pub) {} >>>> private: >>>> my_underlying_library::Publisher* pub_; >>>> }; >>>> >>>> class SubscriberImpl : public virtual GstDaemon::Subscriber::Server { >>>> protected: >>>> SubscriberImpl(my_underlying_library::Subscriber* sub) : sub_(sub) {} >>>> >>>> kj::Promise<void> listenTo(ListenToContext context) override { >>>> auto pub = context.getParams().getPublisher(); // GstDaemon::Publisher >>>> ::Client >>>> // ??? = PublisherImpl::pub_ >>>> sub_->listenTo(???) >>>> } >>>> >>>> private: >>>> my_underlying_library::Subscriber* sub_; >>>> }; >>>> >>>> Now, from the client, I wanted to do something like this: >>>> //GstDaemon::Subscriber::Client subscriber; // already returned by the >>>> server >>>> //GstDaemon::Publisher::Client publisher; // already returned by the >>>> server >>>> auto request = subscriber.listenToRequest(); >>>> request.setPublisher(publisher); >>>> auto promise = request.send(); >>>> >>>> However, as you can see, on the server it's not possible to get the pub_ >>>> pointer when the listenTo method is called. Is there any way I can get >>>> a reference to the PublisherImpl here ? >>>> >>>> -- >>>> You received this message because you are subscribed to the Google >>>> Groups "Cap'n Proto" group. >>>> To unsubscribe from this group and stop receiving emails from it, send >>>> an email to [email protected]. >>>> To view this discussion on the web visit >>>> https://groups.google.com/d/msgid/capnproto/488a63c6-92bc-4bc8-9ab8-e648d3a577bfn%40googlegroups.com >>>> >>>> <https://groups.google.com/d/msgid/capnproto/488a63c6-92bc-4bc8-9ab8-e648d3a577bfn%40googlegroups.com?utm_medium=email&utm_source=footer> >>>> . >>>> >>> -- >> You received this message because you are subscribed to the Google Groups >> "Cap'n Proto" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to [email protected]. >> > To view this discussion on the web visit >> https://groups.google.com/d/msgid/capnproto/45982dae-5fb0-4adb-8b15-9fea70506d25n%40googlegroups.com >> >> <https://groups.google.com/d/msgid/capnproto/45982dae-5fb0-4adb-8b15-9fea70506d25n%40googlegroups.com?utm_medium=email&utm_source=footer> >> . >> > -- You received this message because you are subscribed to the Google Groups "Cap'n Proto" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/capnproto/8c279b5e-0fe0-4dac-af58-22eeda468c92n%40googlegroups.com.
