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?
thisCap()
only works after at least oneClient
object has been created pointing at your server object. To create that initialClient
, you can simply declare a variable of the client type and initialize it to your server object, like so:If you want to keep a reference to the underlying server object even after constructing a
Client
, you can do something like:Note that once the first
Client
has been created, the server will be destroyed as soon as there are no longer anyClient
s pointing to it (including remoteClient
s). So if you want to make sure your reference stays live, make sure you also keep a copy of theClient
.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 yourgetCapability()
method. This is because if the caller isn't already holding aClient
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 likegetCapability()
.