Hi Codie,
While Cap'n Proto is compatible with shared memory, it currently does not provide much in the way of helpers for using it. You'll have to do a number of things yourself.
You can use ftruncate() to set the size extremely large, and then mmap() in the whole thing. Only the pages that you actually write to will be allocated (I think), so this way you don't have to worry about guessing in advance how much to allocate -- just allocate something that's far more than enough.
Once you have a shared memory region set up, you'll need to implement a custom subclass of capnp::MessageBuilder which allocates segments in this space. When you want to transmit to the receiving process, you'll probably need to call builder.getSegmentsForOutput(), construct a segment table based on the offset of each segment from the start of the shared memory space, and transmit that table over a socket or pipe to the receiving process. The receiving process will then need a custom subclass of capnp::MessageReader which can accept this table and read the segments from shared memory. Eventually, the receiving process will need to communicate back when it is done with the message, so that the sending process can free up the segments for reuse.
If you want to transmit messages in both directions, you'll probably want to create two shared memory regions, one for each direction. This way the sending side is always responsible for keeping track of which parts of the region are currently in-use. You can even map the memory read-only on the receiving side, for extra safety.
This design still calls for a socket used to transmit segment tables and other synchronization messages, though the main payload is in shared memory. If you want to avoid a socket altogether, you could devise a protocol that uses POSIX semaphores (or even futexes) located in shared memory for signaling. But personally I'd go with the socket, since it's much easier for the receiving end to listen for events on multiple sockets at the same time.