flatbuffer使用教程

一、定义scheme

Tables

FlatBuffers 中定义对象的主要方式,由名称和字段列表组成。每个字段都有一个名称、一个类型和一个可选的默认值。
如果架构中未指定默认值,则标量类型的默认值将为 0 ,其他类型的默认值将为 null 。

  • 限制
  1. 只能在表定义的末尾在架构中添加新字段,如果您希望灵活地在架构中使用任何顺序的字段,您可以手动分配 id。
  2. 无法从架构中删除不再使用的字段,但您可以简单地停止将它们写入数据中以获得几乎相同的效果。此外,您可以将它们标记为 deprecated
  3. 如果您可以更改代码,则可以更改字段名称和表名称,直到您也在那里重命名它们为止。

Structs

与表类似,只是现在没有任何字段是可选的(因此也没有默认值),并且不能添加或弃用字段。结构体只能包含标量或其他结构体。将此用于您非常确定不会进行任何更改的简单对象。
结构比表使用更少的内存,并且访问速度更快

Types

  • 内置类型

    • 8 bit: byte (int8), ubyte (uint8), bool
    • 16 bit: short (int16), ushort (uint16)
    • 32 bit: int (int32), uint (uint32), float (float32)
    • 64 bit: long (int64), ulong (uint64), double (float64)
      其中括号中的类型名称是别名
  • 内置非标量类型:

  • [type]

  • string 只能保存 UTF-8 或 7 位 ASCII。对于其他文本编码或一般二进制数据,请使用向量 [byte]

一旦使用字段,您就无法更改它们的类型,但相同大小的数据除外

Array

数组是固定长度元素集合的便捷简写。

  • 比如说:
struct Vec3 {
    x:float;
    y:float;
    z:float;
}
  • 可以替换为:
struct Vec3 {
    v:[float:3];
}

默认值、可选值和必需值

枚举

定义一系列命名常量,每个常量都有一个给定值,或者比前一个值增加 1。默认的第一个值为 0 。

通常,枚举值只能被添加,不能被删除(枚举不会被弃用)。这需要代码通过处理未知的枚举值来处理自身的前向兼容性。

工会(Unions)

联合与枚举共享许多属性,但您使用表名称而不是常量的新名称。然后,您可以声明一个联合字段,它可以保存对任何这些类型的引用,此外还会生成一个后缀为 _type 的字段,该字段保存相应的枚举值,让您知道要转换哪种类型到运行时。

namespace

仅C++和java代码生成的时候有这个概念。

其它

  • Root Type
    这声明了您认为是序列化数据的根表。这对于解析不包含对象类型信息的 JSON 数据尤其重要。

二、在C++中使用

schema

namespace dshengChen;

enum Color : byte { Red = 1, Green, Blue }

struct Son {
  x:float;
  y:float;
  z:float;
}

table Monster {
  son:Son;
  name:string;
  age:uint8;
  color:Color = Blue;
}

root_type Monster;

使用指令: 将schema编译为c++版本和python版本的代码。

flatc --cpp -o output_folder_path schema_path
flatc --python -o output_folder_path schema_path

序列化

FlatBuffers 的核心是内存效率,这就是为什么它的基本 API 是围绕使用尽可能少的内存而编写的。这确实使 API 变得更加笨拙(需要对所有数据进行预序构建,并使突变变得更加困难)。


void serialization_data(string user_name, uint8_t user_age)
{
    flatbuffers::FlatBufferBuilder builder;
    auto name = builder.CreateString(user_name);
    dshengChen::Son son(0.1, 0.2, 0.3);
    auto m = dshengChen::CreateMonster(builder, &son, name, user_age, dshengChen::Color_Green);
    builder.Finish(m);
    // 获取 FlatBuffer 数据指针和大小
    const uint8_t *buffer = builder.GetBufferPointer();
    size_t size = builder.GetSize();
    std::ofstream outfile(filePath, std::ios::binary);
    std::vector<char> data(size);
    std::memcpy(data.data(), buffer, size);
    outfile.write(data.data(), size);
    outfile.close();
}

反序列化

void deserialization_data()
{
    ifstream in_file(filePath, std::ios::binary);
    if (in_file.is_open())
    {
        in_file.seekg(0, std::ios::end);
        std::streamsize fileSize = in_file.tellg();
        in_file.seekg(0, std::ios::beg);
        // 读取文件内容到缓冲区
        std::vector<char> buffer(fileSize);
        in_file.read(buffer.data(), fileSize);
        using namespace dshengChen;
        auto parsed_person = GetMonster(buffer.data());
        int age = parsed_person->age();
        Color c = parsed_person->color();
        cout << "\t age is: " << age;
        cout << "\t name is: " << parsed_person->name()->c_str();
        cout << "\t color is: " << (int)c << endl;
    }
    // 关闭文件
    in_file.close();
}

c++ flatbuffer的cmake工程

cmake_minimum_required(VERSION 3.6)
project(py11_t VERSION 0.1.0 LANGUAGES C CXX)

set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_C_STANDARD 17)

include(CPack)

include(FetchContent)
FetchContent_Declare(
    flatbuffers
    GIT_REPOSITORY https://github.com/google/flatbuffers.git
    GIT_TAG v23.5.26
)
FetchContent_MakeAvailable(flatbuffers)

include_directories("./generated")
add_executable(run_e test.cpp)
target_link_libraries(run_e PRIVATE flatbuffers)

# flatc --cpp ./example.fbs -o generated

新增一个代码实例


#include "./generated/example_generated.h"
#include <fstream>
#include <iostream>
#include <string>

using namespace std;

int main() {
    cout << "hi" << endl;
    // 创建 FlatBuffer 构建器
    flatbuffers::FlatBufferBuilder builder;

    // 创建 Person 对象
    auto name1 = builder.CreateString("11111 Doe");
    auto name2 = builder.CreateString("2222 5555");
    auto person1 = CreatePerson(builder, 123, name1, 25, Color::Color_Green);
    auto person2 = CreatePerson(builder, 143, name2, 25, Color::Color_Green);
    vector<flatbuffers::Offset<Person>> p;
    p.emplace_back(person1);
    p.emplace_back(person2);
    auto p_list = builder.CreateVector(p);

    auto schcool_name = builder.CreateString("china school");
    auto s = CreateSchool(builder, p_list, schcool_name);

    // 完成 FlatBuffer 构建
    builder.Finish(s);

    // 获取 FlatBuffer 数据指针和大小
    const uint8_t *buffer = builder.GetBufferPointer();
    size_t size = builder.GetSize();
    cout << "builder size:" << size;
    std::string filePath = "./cds_.bin";

    std::ofstream outfile(filePath, std::ios::binary);
    std::vector<char> data(size);
    std::memcpy(data.data(), buffer, size);
    outfile.write(data.data(), size);
    outfile.close();

    ifstream in_file(filePath, std::ios::binary);
    // 读取文件内容到缓冲区
    in_file.seekg(0, std::ios::end);
    std::streamsize fileSize = in_file.tellg();
    in_file.seekg(0, std::ios::beg);
    std::vector<char> v(fileSize);
    in_file.read(v.data(), fileSize);

    // 反序列化
    auto school = GetSchool(v.data());
    cout << "----------------------------\n\n";
    cout << school->school_name()->c_str() << endl;
    cout << school->p()->Get(0)->name()->c_str() << endl;
    cout << school->p()->Get(1)->name()->c_str() << endl;

    return 0;
}


  • cmake
// adress sanitize
set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")
set (CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")

add_custom_command(
    OUTPUT example_generated.h
    COMMAND flatc --cpp -o ./generated/ "${CMAKE_HOME_DIRECTORY}/example.fbs"
    COMMAND flatc --python -o ./generated/ "${CMAKE_HOME_DIRECTORY}/example.fbs"
    COMMAND cp -rf "${CMAKE_BINARY_DIR}/generated" "${CMAKE_HOME_DIRECTORY}"
    COMMENT "Processing data for the application"
)
add_custom_target(generate_flat_buffer ALL DEPENDS example_generated.h)

  • schema
enum Color:byte { Red = 0, Green, Blue = 2 }

table Person {
  id: int;
  name: string;
  age: short;
  col: Color;
}

table School {
    p: [Person];
    school_name: string;
}

root_type School;


  • 24
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
mnn flatbuffer是指使用Flatbuffers库来处理MNN(Mobile Neural Network)模型的二进制缓存文件。在MNN中,它使用Flatbuffers来序列化和反序列化模型数据,以实现高效的加载和传输。通过使用Flatbuffers,MNN可以快速地将模型数据序列化为二进制buffer,并在需要时快速反序列化,从而提高了加载模型的速度。此外,Flatbuffers还具有占用空间小、使用简单、代码自动化生成等优点,使其在移动端应用中更加适用。因此,mnn flatbuffer是指使用Flatbuffers来处理MNN模型缓存的方式。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [MNN Interpreter and Session](https://blog.csdn.net/yiran103/article/details/108552734)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [序列化与反序列化之Flatbuffers(一):初步使用](https://blog.csdn.net/hsqyc/article/details/115719054)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

早睡的叶子

你的鼓励就是我的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值