diff --git a/scripts/generate_code.py b/scripts/generate_code.py index c34e0ba57..500a3706e 100755 --- a/scripts/generate_code.py +++ b/scripts/generate_code.py @@ -333,6 +333,16 @@ flatc( schema="arrays_test.fbs", ) +flatc( + ["--cpp", "--gen-mutable", "--gen-object-api", "--reflect-names"], + schema="native_type_test.fbs", +) + +flatc( + ["--cpp", "--gen-mutable", "--gen-compare", "--gen-object-api", "--reflect-names"], + schema="native_inline_table_test.fbs", +) + flatc( RUST_OPTS, prefix="arrays_test", diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index 833d462f4..1fa066525 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -3217,7 +3217,13 @@ class CppGenerator : public BaseGenerator { const auto pack_name = struct_attrs.Lookup("native_type_pack_name"); if (pack_name) { unpack_call += pack_name->constant; } unpack_call += "(*" + val + ")"; - return unpack_call; + if (invector || afield.native_inline) { + return unpack_call; + } else { + const auto name = native_type->constant; + const auto ptype = GenTypeNativePtr(name, &afield, true); + return ptype + "(new " + name + "(" + unpack_call + "))"; + } } else if (invector || afield.native_inline) { return "*" + val; } else { @@ -3601,12 +3607,16 @@ class CppGenerator : public BaseGenerator { if (IsStruct(field.value.type)) { const auto &struct_attribs = field.value.type.struct_def->attributes; const auto native_type = struct_attribs.Lookup("native_type"); - if (native_type) { + if (native_type && field.native_inline) { code += "::flatbuffers::Pack"; const auto pack_name = struct_attribs.Lookup("native_type_pack_name"); if (pack_name) { code += pack_name->constant; } code += "(" + value + ")"; + } else if (native_type && !field.native_inline) { + code += WrapInNameSpace(*field.value.type.struct_def) + "{};"; + code += " if (_o->" + Name(field) + ") _" + Name(field) + + " = ::flatbuffers::Pack(*_o->" + Name(field) + ")"; } else if (field.native_inline) { code += "&" + value; } else { @@ -3735,16 +3745,22 @@ class CppGenerator : public BaseGenerator { if (field->deprecated) { continue; } bool pass_by_address = false; + bool check_ptr = false; if (field->value.type.base_type == BASE_TYPE_STRUCT) { if (IsStruct(field->value.type)) { auto native_type = field->value.type.struct_def->attributes.Lookup("native_type"); + auto native_inline = field->attributes.Lookup("native_inline"); if (native_type) { pass_by_address = true; } + if (native_type && !native_inline) { check_ptr = true; } } } // Call the CreateX function using values from |_o|. - if (pass_by_address) { + if (pass_by_address && check_ptr) { + code_ += ",\n _o->" + Name(*field) + " ? &_" + Name(*field) + + " : nullptr\\"; + } else if (pass_by_address) { code_ += ",\n &_" + Name(*field) + "\\"; } else { code_ += ",\n _" + Name(*field) + "\\"; diff --git a/tests/native_type_test.fbs b/tests/native_type_test.fbs index e22150f5b..2b7d5474e 100644 --- a/tests/native_type_test.fbs +++ b/tests/native_type_test.fbs @@ -17,6 +17,8 @@ struct Vector3DAlt (native_type:"Native::Vector3D", native_type_pack_name:"Vecto table ApplicationData { vectors:[Vector3D]; vectors_alt:[Vector3DAlt]; + position:Vector3D; + position_inline:Vector3D (native_inline); } root_type ApplicationData; diff --git a/tests/native_type_test_generated.h b/tests/native_type_test_generated.h index afea06341..55585f324 100644 --- a/tests/native_type_test_generated.h +++ b/tests/native_type_test_generated.h @@ -117,6 +117,12 @@ struct ApplicationDataT : public ::flatbuffers::NativeTable { typedef ApplicationData TableType; std::vector vectors{}; std::vector vectors_alt{}; + std::unique_ptr position{}; + Native::Vector3D position_inline{}; + ApplicationDataT() = default; + ApplicationDataT(const ApplicationDataT &o); + ApplicationDataT(ApplicationDataT&&) FLATBUFFERS_NOEXCEPT = default; + ApplicationDataT &operator=(ApplicationDataT o) FLATBUFFERS_NOEXCEPT; }; struct ApplicationData FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { @@ -127,7 +133,9 @@ struct ApplicationData FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { } enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { VT_VECTORS = 4, - VT_VECTORS_ALT = 6 + VT_VECTORS_ALT = 6, + VT_POSITION = 8, + VT_POSITION_INLINE = 10 }; const ::flatbuffers::Vector *vectors() const { return GetPointer *>(VT_VECTORS); @@ -141,12 +149,26 @@ struct ApplicationData FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { ::flatbuffers::Vector *mutable_vectors_alt() { return GetPointer<::flatbuffers::Vector *>(VT_VECTORS_ALT); } + const Geometry::Vector3D *position() const { + return GetStruct(VT_POSITION); + } + Geometry::Vector3D *mutable_position() { + return GetStruct(VT_POSITION); + } + const Geometry::Vector3D *position_inline() const { + return GetStruct(VT_POSITION_INLINE); + } + Geometry::Vector3D *mutable_position_inline() { + return GetStruct(VT_POSITION_INLINE); + } bool Verify(::flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_VECTORS) && verifier.VerifyVector(vectors()) && VerifyOffset(verifier, VT_VECTORS_ALT) && verifier.VerifyVector(vectors_alt()) && + VerifyField(verifier, VT_POSITION, 4) && + VerifyField(verifier, VT_POSITION_INLINE, 4) && verifier.EndTable(); } ApplicationDataT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; @@ -164,6 +186,12 @@ struct ApplicationDataBuilder { void add_vectors_alt(::flatbuffers::Offset<::flatbuffers::Vector> vectors_alt) { fbb_.AddOffset(ApplicationData::VT_VECTORS_ALT, vectors_alt); } + void add_position(const Geometry::Vector3D *position) { + fbb_.AddStruct(ApplicationData::VT_POSITION, position); + } + void add_position_inline(const Geometry::Vector3D *position_inline) { + fbb_.AddStruct(ApplicationData::VT_POSITION_INLINE, position_inline); + } explicit ApplicationDataBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); @@ -178,8 +206,12 @@ struct ApplicationDataBuilder { inline ::flatbuffers::Offset CreateApplicationData( ::flatbuffers::FlatBufferBuilder &_fbb, ::flatbuffers::Offset<::flatbuffers::Vector> vectors = 0, - ::flatbuffers::Offset<::flatbuffers::Vector> vectors_alt = 0) { + ::flatbuffers::Offset<::flatbuffers::Vector> vectors_alt = 0, + const Geometry::Vector3D *position = nullptr, + const Geometry::Vector3D *position_inline = nullptr) { ApplicationDataBuilder builder_(_fbb); + builder_.add_position_inline(position_inline); + builder_.add_position(position); builder_.add_vectors_alt(vectors_alt); builder_.add_vectors(vectors); return builder_.Finish(); @@ -188,17 +220,36 @@ inline ::flatbuffers::Offset CreateApplicationData( inline ::flatbuffers::Offset CreateApplicationDataDirect( ::flatbuffers::FlatBufferBuilder &_fbb, const std::vector *vectors = nullptr, - const std::vector *vectors_alt = nullptr) { + const std::vector *vectors_alt = nullptr, + const Geometry::Vector3D *position = nullptr, + const Geometry::Vector3D *position_inline = nullptr) { auto vectors__ = vectors ? _fbb.CreateVectorOfStructs(*vectors) : 0; auto vectors_alt__ = vectors_alt ? _fbb.CreateVectorOfStructs(*vectors_alt) : 0; return Geometry::CreateApplicationData( _fbb, vectors__, - vectors_alt__); + vectors_alt__, + position, + position_inline); } ::flatbuffers::Offset CreateApplicationData(::flatbuffers::FlatBufferBuilder &_fbb, const ApplicationDataT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); +inline ApplicationDataT::ApplicationDataT(const ApplicationDataT &o) + : vectors(o.vectors), + vectors_alt(o.vectors_alt), + position((o.position) ? new Native::Vector3D(*o.position) : nullptr), + position_inline(o.position_inline) { +} + +inline ApplicationDataT &ApplicationDataT::operator=(ApplicationDataT o) FLATBUFFERS_NOEXCEPT { + std::swap(vectors, o.vectors); + std::swap(vectors_alt, o.vectors_alt); + std::swap(position, o.position); + std::swap(position_inline, o.position_inline); + return *this; +} + inline ApplicationDataT *ApplicationData::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const { auto _o = std::unique_ptr(new ApplicationDataT()); UnPackTo(_o.get(), _resolver); @@ -210,6 +261,8 @@ inline void ApplicationData::UnPackTo(ApplicationDataT *_o, const ::flatbuffers: (void)_resolver; { auto _e = vectors(); if (_e) { _o->vectors.resize(_e->size()); for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->vectors[_i] = ::flatbuffers::UnPack(*_e->Get(_i)); } } else { _o->vectors.resize(0); } } { auto _e = vectors_alt(); if (_e) { _o->vectors_alt.resize(_e->size()); for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->vectors_alt[_i] = ::flatbuffers::UnPackVector3DAlt(*_e->Get(_i)); } } else { _o->vectors_alt.resize(0); } } + { auto _e = position(); if (_e) _o->position = std::unique_ptr(new Native::Vector3D(::flatbuffers::UnPack(*_e))); } + { auto _e = position_inline(); if (_e) _o->position_inline = ::flatbuffers::UnPack(*_e); } } inline ::flatbuffers::Offset ApplicationData::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const ApplicationDataT* _o, const ::flatbuffers::rehasher_function_t *_rehasher) { @@ -222,10 +275,14 @@ inline ::flatbuffers::Offset CreateApplicationData(::flatbuffer struct _VectorArgs { ::flatbuffers::FlatBufferBuilder *__fbb; const ApplicationDataT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; auto _vectors = _o->vectors.size() ? _fbb.CreateVectorOfNativeStructs(_o->vectors) : 0; auto _vectors_alt = _o->vectors_alt.size() ? _fbb.CreateVectorOfNativeStructs(_o->vectors_alt, ::flatbuffers::PackVector3DAlt) : 0; + auto _position = Geometry::Vector3D{}; if (_o->position) _position = ::flatbuffers::Pack(*_o->position); + auto _position_inline = ::flatbuffers::Pack(_o->position_inline); return Geometry::CreateApplicationData( _fbb, _vectors, - _vectors_alt); + _vectors_alt, + _o->position ? &_position : nullptr, + &_position_inline); } inline const ::flatbuffers::TypeTable *Vector3DTypeTable() { @@ -267,7 +324,9 @@ inline const ::flatbuffers::TypeTable *Vector3DAltTypeTable() { inline const ::flatbuffers::TypeTable *ApplicationDataTypeTable() { static const ::flatbuffers::TypeCode type_codes[] = { { ::flatbuffers::ET_SEQUENCE, 1, 0 }, - { ::flatbuffers::ET_SEQUENCE, 1, 1 } + { ::flatbuffers::ET_SEQUENCE, 1, 1 }, + { ::flatbuffers::ET_SEQUENCE, 0, 0 }, + { ::flatbuffers::ET_SEQUENCE, 0, 0 } }; static const ::flatbuffers::TypeFunction type_refs[] = { Geometry::Vector3DTypeTable, @@ -275,10 +334,12 @@ inline const ::flatbuffers::TypeTable *ApplicationDataTypeTable() { }; static const char * const names[] = { "vectors", - "vectors_alt" + "vectors_alt", + "position", + "position_inline" }; static const ::flatbuffers::TypeTable tt = { - ::flatbuffers::ST_TABLE, 2, type_codes, type_refs, nullptr, nullptr, names + ::flatbuffers::ST_TABLE, 4, type_codes, type_refs, nullptr, nullptr, names }; return &tt; } diff --git a/tests/test.cpp b/tests/test.cpp index a374da575..1564fa706 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -909,6 +909,9 @@ void NativeTypeTest() { const int N = 3; Geometry::ApplicationDataT src_data; + src_data.position = flatbuffers::unique_ptr( + new Native::Vector3D(1.0f, 2.0f, 3.0f)); + src_data.position_inline = Native::Vector3D(4.0f, 5.0f, 6.0f); src_data.vectors.reserve(N); src_data.vectors_alt.reserve(N); @@ -924,6 +927,13 @@ void NativeTypeTest() { auto dstDataT = Geometry::UnPackApplicationData(fbb.GetBufferPointer()); + TEST_EQ(dstDataT->position->x, 1.0f); + TEST_EQ(dstDataT->position->y, 2.0f); + TEST_EQ(dstDataT->position->z, 3.0f); + TEST_EQ(dstDataT->position_inline.x, 4.0f); + TEST_EQ(dstDataT->position_inline.y, 5.0f); + TEST_EQ(dstDataT->position_inline.z, 6.0f); + for (int i = 0; i < N; ++i) { const Native::Vector3D &v = dstDataT->vectors[i]; TEST_EQ(v.x, 10 * i + 0.1f);