Search code examples
pythonflatbuffers

flatbuffers nesting vectors in table not working


I am new to flatbuffers, and am trying to create a flatbuffers table with a nested vector. Since that can't be done according to the flatbuffer specs, I have wrapped the outer vector in another table. Here is the flatbuffers IDL:

namespace world;

table Point {
   lat:double;
   lon:double;
}

table Polygon {
   vertices:[Point];
}

table Country {
   id:int32;
   area:[Polygon];
}

root_type Country;

Then I wrote a writer in python:

import flatbuffers
from world import Country, Polygon, Point

b = flatbuffers.Builder(0)
polys = []
for a in range(3):
    points = []
    for lon, lat in [[1,2], [3,4], [5,6]][:a+1]:
        Point.PointStart(b)
        Point.PointAddLat(b, lat + a*10)
        Point.PointAddLon(b, lon + a*10)
        t = Point.PointEnd(b)
        points.append(t)

    points.reverse()
    Polygon.PolygonStartVerticesVector(b, len(points))
    for p in points:
        b.PrependUOffsetTRelative(p)
    vertices = b.EndVector(len(points))

    Polygon.PolygonStart(b)
    Polygon.PolygonAddVertices(b, vertices)
    Polygon.PolygonAddExtra(b, 1)
    polys.append(Polygon.PolygonEnd(b))

polys.reverse()
Country.CountryStartAreaVector(b, len(polys))
for p in polys:
    b.PrependUOffsetTRelative(p)
area = b.EndVector(len(polys))

Country.CountryStart(b)
Country.CountryAddArea(b, area)
pos = Country.CountryEnd(b)
b.Finish(pos)

raw_country = b.Output()

with open("output.pb", "wb") as out:
    out.write(raw_country)

Finally, I wrote the reader:

import flatbuffers
import world.Country

with open("output.pb", "rb") as inf:
    buf = bytearray(inf.read())
    country = world.Country.Country.GetRootAsCountry(buf, 0)
    for ii in range(country.AreaLength()):
        poly = country.Area(ii)
        print('[',poly.VerticesLength(), end=' ')
        for jj in range(poly.VerticesLength()):
            v = poly.Vertices(ii)
            print('[{},{}]'.format(v.Lat(), v.Lon()), end=', ')
        print(']')

(sorry for so much code -- I tried to simplify things as much as possible). OK, so when I run the writer, no errors, everything seems to be grand. When I run the reader, though, while I don't get any errors, I also do not get the output I was expecting. Instead of:

[ 1 [2.0,1.0], ]

[ 2 [12.0,11.0], [14.0,13.0], ]

[ 3 [22.0,21.0], [24.0,23.0], [26.0,25.0], ]

I get:

[ 1 [2.0,1.0], ]

[ 2 [14.0,13.0], [14.0,13.0], ]

[ 3 [26.0,25.0], [26.0,25.0], [26.0,25.0], ]

In other words, instead of unique values in the child vectors, I get repeated values. I wrote this same program in C++ and had the same undesirable outcome, so I believe it is a misunderstanding with flatbuffers rather than a simple typo. Furthermore, when I removed the outside vector (and its wrapping table) the program worked as expected. I got one long list of differing values. Can anyone see what I am missing?


Solution

  • v = poly.Vertices(ii).. did you mean v = poly.Vertices(jj) ? Do you have the same in C++?