google / flatbuffers

FlatBuffers: Memory Efficient Serialization Library
https://flatbuffers.dev/
Apache License 2.0
23.28k stars 3.25k forks source link

data does not survive serialization (C#) #3821

Closed ophilbinbriscoe closed 8 years ago

ophilbinbriscoe commented 8 years ago

Hey, hopefully I'm doing something wrong and this is a quick fix.

I have the following table defined:

namespace FlowControl.Data;

table Test {
    text:string;
}

root_type Test;

Here is the C# it generates:

// automatically generated, do not modify

namespace FlowControl.Data
{

using System;
using FlatBuffers;

public sealed class Test : Table {
  public static Test GetRootAsTest(ByteBuffer _bb) { return GetRootAsTest(_bb, new Test()); }
  public static Test GetRootAsTest(ByteBuffer _bb, Test obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
  public Test __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }

  public string Text { get { int o = __offset(4); return o != 0 ? __string(o + bb_pos) : null; } }
  public ArraySegment<byte>? GetTextBytes() { return __vector_as_arraysegment(4); }

  public static Offset<Test> CreateTest(FlatBufferBuilder builder,
      StringOffset textOffset = default(StringOffset)) {
    builder.StartObject(1);
    Test.AddText(builder, textOffset);
    return Test.EndTest(builder);
  }

  public static void StartTest(FlatBufferBuilder builder) { builder.StartObject(1); }
  public static void AddText(FlatBufferBuilder builder, StringOffset textOffset) { builder.AddOffset(0, textOffset.Value, 0); }
  public static Offset<Test> EndTest(FlatBufferBuilder builder) {
    int o = builder.EndObject();
    return new Offset<Test>(o);
  }
  public static void FinishTestBuffer(FlatBufferBuilder builder, Offset<Test> offset) { builder.Finish(offset.Value); }
};

}

And here is the test I'm running:

var s = "My test string. " + DateTime.Now;

var fbb = new FlatBufferBuilder( 1 );

var offset = fbb.CreateString( s );

Data.Test.StartTest( fbb );
Data.Test.AddText( fbb, offset );
Data.Test.FinishTestBuffer( fbb, Data.Test.EndTest( fbb ) );

var bb = new ByteBuffer( fbb.DataBuffer.Data );

var test = Data.Test.GetRootAsTest( bb );

Assert.NotNull( test, "Deserialized table is null." );

Assert.NotNull( test.Text, "Deserialized string is null." );

Assert.Equals( test.Text, s, "Strings do not match." );

I'm failing at the 2nd assert (the string is reading back as null).

Do I need to be calling fbb.Finish( ... ) somewhere? I've seen it used seemingly interchangeably with SomeTable.FinishSomeTableBuffer( ... ).

Let me know if there's anything else I can provide. Clearly I'm new to FlatBuffers.

Update: Experimenting a little more, I changed the line above:

var bb = new ByteBuffer( fbb.DataBuffer.Data );

To:

var bb = fbb.DataBuffer;

And my test is now passing. I'm going to continue searching the documentation for instructions on how to properly access the byte array in a ByteBuffer for writing to a file / sending over network etc., as this part is glossed over in the Tutorial section.

ghost commented 8 years ago

Indeed, I'll make how to access the bytes more obvious in docs.