Hi John,

You have to copy into a new message, as you have done.

The reason is, the message tree pointed to by the AnyPointer is not
necessarily contiguous in memory. Unlike most other serialization out
there, Cap'n Proto objects point to their child objects using pointers that
can cross over other object in between. (Most serializations use nested
encoding instead, but this doesn't work well with zero-copy.) Generally,
objects will be ordered in memory in the order in which they were
allocated. Typically programs writing a message will work on one part of
the tree at a time, in which case you'll get a depth-first ordering, but
that's not guaranteed. If a program switches back and forth between
building different parts of the message, the objects will end up
interleaved in memory.

So the only way to get an object tree into contiguous memory is to copy it
into a new arena -- i.e. a new MessageBuilder.

You could, however, avoid the second copy implied by
`messageToFlatArray()`. Instead, before making the copy, use
`getMsg().targetSize().wordCount` to see how much memory the message tree
takes. Add 1 word for the root pointer. Then pass this to
MallocMessageBuilder's constructor as the first segment size. Now copy the
message. If you then call messageBuilder.getSegmentsForOutput(), you should
find there is only one segment, containing the root pointer followed by the
content. So now you can use that data without making an extra copy...

-Kenton

On Fri, May 15, 2020 at 4:27 AM John Demme <[email protected]> wrote:

> I've been playing with this a bit and the closest I've been able to get is
> constructing a new message with the AnyPointer at the root. That, however,
> prepends a struct pointer to the whole thing. I can just chop it off, but
> I'm thinking there must be a better way.
>
>     auto msg = context.getParams().getMsg(); // AnyPointer
>     MallocMessageBuilder messageBuilder;
>     messageBuilder.setRoot(msg);
>     auto flatWordsArray = messageToFlatArray(messageBuilder);
>     auto byteArray = flatWordsArray.asBytes();
>
>
> ~John
>
>
> On Thursday, May 14, 2020 at 11:30:38 PM UTC-7, John Demme wrote:
>>
>> Hi-
>>
>> In the C++ API, is there an (easy) way to get the binary encoded message
>> of an AnyPointer field? Or a generic field? (If I understand, they're
>> encoded the same under the hood.) I don't think anyPointer->getAs<Data>()
>> would work, would it?
>>
>> The background here is that I'm trying to write a generic proxy for
>> CapnProto messages using CapnProto RPC. Since I'm not re-compiling the
>> proxy itself, it cannot know the possible types for AnyPointer. Since
>> messages don't need any schema data to be traversed (though not
>> interpreted) correctly, this *should *be possible.
>>
>> To be more concrete:
>> interface ProxyChannel {
>>     send @0 (msg :AnyPointer);
>>     recv @1 () -> (respMsg :AnyPointer);
>> }
>>
>> I'm using :Data instead of :AnyPointer now, but that puts a unnecessary
>> burden on the clients.
>>
>> ~John
>>
> --
> 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/7f1b3509-0bac-4854-8256-d85a718031d7%40googlegroups.com
> <https://groups.google.com/d/msgid/capnproto/7f1b3509-0bac-4854-8256-d85a718031d7%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/CAJouXQ%3DtsPpFRLW6Xfpp8Y1S9JQ7qCTF0mPXBNZZbxjMcKp68Q%40mail.gmail.com.

Reply via email to