Reputation: 8063
I am playing with the calculator-server.c++
sample, where I try to extract thisCap()
to have a capability to the server from outside. Because thisCap()
is protected
, I wrote my own public getCapability()
:
class CalculatorImpl final: public Calculator::Server {
// Implementation of the Calculator Cap'n Proto interface.
public:
Calculator::Client getCapability() {
return thisCap();
}
Then I create the server and call getCapability()
from my main:
auto calculatorImpl = kj::heap<CalculatorImpl>();
auto myCapability = calculatorImpl->getCapability();
But this segfaults:
Program received signal SIGSEGV, Segmentation fault.
0x000055555573c847 in capnp::Capability::Server::thisCap() ()
(gdb) bt
#0 0x000055555573c847 in capnp::Capability::Server::thisCap() ()
#1 0x000055555573c93d in Calculator::Server::thisCap() ()
#2 0x000055555573e541 in CalculatorImpl::getCapability() ()
#3 0x0000555555739a98 in main ()
Following the source, I end up on this:
Capability::Client Capability::Server::thisCap() {
return Client(thisHook->addRef());
}
So it seems like thisHook
is a nullptr, which makes sense since that's how it is initialized.
I just don't really get at which point it get initialized (this explains when it is definitely not initialized).
Any idea?
Upvotes: 0
Views: 129
Reputation: 45296
thisCap()
only works after at least one Client
object has been created pointing at your server object. To create that initial Client
, you can simply declare a variable of the client type and initialize it to your server object, like so:
Calculator::Client cap = kj::heap<CalculatorImpl>();
If you want to keep a reference to the underlying server object even after constructing a Client
, you can do something like:
kj::Own<CalculatorImpl> server = kj::heap<CalculatorImpl>();
CalculatorImpl& ref = *server;
Calculator::Client cap = kj::mv(server);
Note that once the first Client
has been created, the server will be destroyed as soon as there are no longer any Client
s pointing to it (including remote Client
s). So if you want to make sure your reference stays live, make sure you also keep a copy of the Client
.
Normally, thisCap()
is used inside the implementation of RPC methods. It's unusual to expose it to external callers in the way you have with your getCapability()
method. This is because if the caller isn't already holding a Client
pointing to the object, then it has no way to know if the object still exists, and so it would be unsafe to call a method like getCapability()
.
Upvotes: 1