Your code only handles the case of a single segment. I recommend using the methods in capnp/serialize.h and org.capnproto.Serialize. I do not recommend using getSegmentsForOutput() nor constructing a MessageReader directly from a segment array, as these are advanced functions that can more easily go wrong.
That said, in your example case, only a single segment should be needed, so something else is wrong too. I don't see any other obvious problems with the code you provided. I suspect a bug exists in the code you didn't show. I recommend you try to verify that the bytes on the receiving end are actually exactly the bytes from the sending end. Try logging the byte values and the size of the segment at each end to make sure everything matches. I think the most likely problem is that somewhere your `char*` is being interpreted as a NUL-terminated string, and is therefore being truncated at the first zero-valued byte. Most likely, the very first byte in the segment is a zero, so probably your ByteBuffer on the Java end ends up being zero-length. This probably leads to the struct appearing to contain only default values, hence goodsId is 0. -Kenton On Sat, Oct 5, 2019 at 11:28 PM 张小 <[email protected]> wrote: > hi Kenton: > I need your help,This problem has been bothering me for many days. > > In c++ server ,code like this > capnp::MallocMessageBuilder message; > FullInfo::Builder fullInfo = message.initRoot<FullInfo>(); > fullInfo.setGoodsId(919731) > > kj::ArrayPtr<const kj::ArrayPtr<const capnp::word>> segments > = message.getSegmentsForOutput(); > kj::ArrayPtr<const capnp::word> segment = segments[0]; > kj::ArrayPtr<const char> chars = segment.asChars(); > const char* mem_buf = chars.begin(); > int32_t mem_buf_len = chars.size(); > > and c++ server send the mem_buf to java_client by rpc call(bytes field) > > *Client and server communicate through protobuf rpc* > > In java_client code like this:() > > com.google.protobuf.ByteString capn_object_bytes = > response.getCapnObject(); > ByteBuffer[] bytes_buffer = new ByteBuffer[1]; > bytes_buffer[0] = capn_object_bytes.asReadOnlyByteBuffer(); > MessageReader message = new MessageReader(bytes_buffer, > ReaderOptions.DEFAULT_READER_OPTIONS); > Display.FullInfo.Reader fullInfo = > message.getRoot(Display.FullInfo.factory); > System.out.println("goodsId:" + fullInfo.getGoodsId()); > > but in java_client ,print goodsId is 0, however in c++ server, I > setGoodsId(919731) ,What's wrong with my method of use? @Kenton > > the fullinfo.capnp code is: > @0xcb70f505c89d1634; > > using Java = import "./compiler/src/main/schema/capnp/java.capnp"; > $Java.package("org.capnproto.examples"); > $Java.outerClassname("Display"); > > struct FullInfo{ > goodsId @1 :Int64; > } > > > > > > 在 2019年10月1日星期二 UTC+8上午3:23:37,Kenton Varda写道: >> >> Are you transmitting one big buffer containing all the segments, or are >> you transmitting each segment separately? >> >> It looks like you're trying to do the latter, but in that case you cannot >> use Serialize.read() to read it. You need to use `new >> MessageReader(segments)`. >> >> -Kenton >> >> On Mon, Sep 30, 2019 at 5:52 AM 张小 <[email protected]> wrote: >> >>> First Time: >>> In C++ server,I Use capnp::DynamicStruct, code like this: >>> capnp::MallocMessageBuilder msg; >>> capnp::DynamicStruct::Builder fullinfo_builder >>> = msg.initRoot<capnp::DynamicStruct>(g_schema); >>> capnp::DynamicStruct::Builder fullInfo = >>> msg.initRoot<capnp::DynamicStruct>(g_schema); >>> >>> capnp::messageToFlatArray(msg); ---->convert it to char* send to >>> java_cliet >>> >>> Java Client ,code like this: >>> MessageReader message >>> = org.capnproto.Serialize.read(capn_object_bytes.asReadOnlyByteBuffer());, >>> Info.Reader adInfo = message.getRoot(Info.factory); >>> >>> Above , My First Time do work , but The Second Time, I do like this ,it >>> do not work: >>> In C++ server, code like this: >>> >>> capnp::MallocMessageBuilder message; >>> Info::Builder info = message.initRoot<Info>(); >>> info.setId(123); >>> kj::ArrayPtr<const kj::ArrayPtr<const capnp::word>> segments = >>> message.getSegmentsForOutput(); >>> >>> then I convert the segments object to char* send to java_client by >>> proto rpc_call (bytes field) >>> >>> >>> Java Client ,code like this: >>> MessageReader message >>> = org.capnproto.Serialize.read(capn_object_bytes.asReadOnlyByteBuffer());, >>> Info.Reader adInfo = message.getRoot(Info.factory); >>> >>> >>> In Second Time, happen Error like this: >>> >>> Exception in thread "main" java.lang.IllegalArgumentException >>> at java.nio.Buffer.limit(Buffer.java:275) >>> at org.capnproto.Serialize.read(Serialize.java:140) >>> at org.capnproto.Serialize.read(Serialize.java:111) >>> >>> How Can I do , In Second Time ,thanks >>> >>> >>> >>> >>> >>> >>> 在 2019年9月30日星期一 UTC+8下午8:29:41,David Renshaw写道: >>>> >>>> On the Java side, you need to first read the bytes into a >>>> `MessageReader`. That's typically done via one of the `Serialize.read()` >>>> methods. >>>> >>>> The `AnyPointer.Reader()` is not intended for external use. Probably we >>>> should make it private. >>>> >>>> >>>> On Mon, Sep 30, 2019 at 6:25 AM 张小 <[email protected]> wrote: >>>> >>>>> C++ server send Capn Object to JavaClient like this >>>>> >>>>> capnp::MallocMessageBuilder message; >>>>> Info::Builder info = message.initRoot<Info>(); >>>>> info.setId(123); >>>>> kj::ArrayPtr<const kj::ArrayPtr<const capnp::word>> segments = >>>>> message.getSegmentsForOutput(); >>>>> >>>>> then I convert the segments object to char* send to java_client by >>>>> proto rpc_call (bytes field) >>>>> >>>>> >>>>> Then In java_client, I do like this to read the capn object >>>>> com.google.protobuf.ByteString capn_object_bytes = >>>>> response.getCapnObject() >>>>> SegmentReader segment = new >>>>> SegmentReader(capn_object_bytes.asReadOnlyByteBuffer(), null); >>>>> AnyPointer.Reader any = new AnyPointer.Reader(segment, 0, >>>>> 64*1024*1024); >>>>> Info.Reader info = any.getAs(Info.factory); >>>>> System.out.println("Id:" + info.getId()); >>>>> >>>>> >>>>> run java_cliet ,happend error like this : >>>>> Exception in thread "main" java.lang.NullPointerException >>>>> at org.capnproto.WireHelpers.readStructPointer(WireHelpers.java:918) >>>>> at >>>>> org.capnproto.StructFactory.fromPointerReaderRefDefault(StructFactory.java:34) >>>>> at org.capnproto.StructFactory.fromPointerReader(StructFactory.java:41) >>>>> at org.capnproto.StructFactory.fromPointerReader(StructFactory.java:24) >>>>> at org.capnproto.AnyPointer$Reader.getAs(AnyPointer.java:56) >>>>> >>>>> >>>>> >>>>> >>>>> -- >>>>> 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/081ab20b-5eae-43d5-a4fc-8230ef39d4a5%40googlegroups.com >>>>> <https://groups.google.com/d/msgid/capnproto/081ab20b-5eae-43d5-a4fc-8230ef39d4a5%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/816c3227-c2b2-4b72-8ead-e707759a257c%40googlegroups.com >>> <https://groups.google.com/d/msgid/capnproto/816c3227-c2b2-4b72-8ead-e707759a257c%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/1e177ff5-e49f-4d4a-b5f3-1c096604bb29%40googlegroups.com > <https://groups.google.com/d/msgid/capnproto/1e177ff5-e49f-4d4a-b5f3-1c096604bb29%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/CAJouXQnwaFj8mGGvOGdTOBKKe35EaWTW45CXvc7e%2B_PXZizi0A%40mail.gmail.com.
