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/CAJouXQmJ6cz_%2BGKsgo82ePNFaerqy27XJcEKMgXAMD3ePzRpvA%40mail.gmail.com.

Reply via email to