
FlatBuffers 与 gRPC 集成指南构建、测试与 C Callback API 代码生成【免费下载链接】flatbuffersFlatBuffers: Memory Efficient Serialization Library项目地址: https://gitcode.com/GitHub_Trending/fl/flatbuffers本篇技术指南以 grpc/README.md 为核心系统讲解在 FlatBuffers 仓库中如何构建并运行 gRPC 集成测试以及如何通过flatc生成基于现代 gRPC Callback API 的 C 服务端与客户端代码。读完本文你将掌握 Linux 环境下 gRPC FlatBuffers 的完整构建流程、Bazel 替代方案、测试运行方式以及四种 RPC 流式形态Unary / Client streaming / Server streaming / Bidi streaming对应的 reactor 返回类型与async_*客户端方法签名。gRPC 支持在 FlatBuffers 仓库中的组织方式FlatBuffers 仓库中的grpc/目录承载了与 gRPC 相关的全部内容整体布局如下grpc/src/compiler/与 gRPC 项目共享的代码生成器源码按语言拆分为 cpp_generator.cc、go_generator.cc、java_generator.cc、python_generator.cc、swift_generator.cc、ts_generator.cc 等配合 schema_interface.h 提供统一的 schema 访问抽象grpc/tests/gRPC 专属测试如 grpctest.cpp 以及回调 API 的编译期测试grpc/examples/Go、Python、Swift、TypeScript 四种语言的 greeter 示例schema 见 greeter.fbsgrpc/samples/greeter/C 版 greeter 示例client.cpp / server.cppgrpc/flatbuffers-java-grpc/Java 侧 gRPC 工具类。文档强调了一个重要约定grpc/src/下的文件与 gRPC 项目共享并在 gRPC 仓库中维护任何改动都应提交到 gRPC 项目而非 FlatBuffers 仓库。这些文件是从 gRPC 拷贝而来同时服务于 Protobuf 与 FlatBuffers 两套代码生成器——这从 cpp_generator.h 的注释可以得到印证“cpp_generator.h/.cc 不直接依赖 gRPC/ProtoBuf因此可以被用于为其他序列化系统如 FlatBuffers生成代码”。grpc/tests/中存放的是 gRPC 专属测试。要编译这些测试必须先构建并安装 gRPC 库然后通过主 FlatBuffers CMake 工程的FLATBUFFERS_BUILD_GRPCTEST选项开启编译。在 Linux 上构建带 gRPC 的 FlatBuffers前置准备下载并安装 gRPC下载、构建并安装 gRPC可参考 gRPC 官方 C 安装指引例如克隆 gRPC 仓库。假设你的 gRPC 克隆位于/your/path/to/grpc_repo。使用自定义安装目录安装 gRPCmake install prefix/your/path/to/grpc_repo/install配置环境变量构建 gRPC 测试需要两个环境变量它们分别告诉 CMake gRPC 的安装位置与 Protobuf 源码位置export GRPC_INSTALL_PATH/your/path/to/grpc_repo/install export PROTOBUF_DOWNLOAD_PATH/your/path/to/grpc_repo/third_party/protobuf配置并编译mkdir build ; cd build cmake -DFLATBUFFERS_BUILD_GRPCTESTON -DGRPC_INSTALL_PATH${GRPC_INSTALL_PATH} -DPROTOBUF_DOWNLOAD_PATH${PROTOBUF_DOWNLOAD_PATH} .. make这三个 CMake 变量在主 CMakeLists.txt 中有严格校验FLATBUFFERS_BUILD_GRPCTEST默认为 OFF第 27 行定义当开启后若未定义GRPC_INSTALL_PATH或PROTOBUF_DOWNLOAD_PATHCMake 会直接报错并提示“See grpc/README.md”。校验通过后CMake 会将${GRPC_INSTALL_PATH}/include与${PROTOBUF_DOWNLOAD_PATH}/src加入 include 搜索路径并把${GRPC_INSTALL_PATH}追加进CMAKE_PREFIX_PATH以帮助查找 gRPC 库。Bazel 用户如果你使用 Bazel 构建可直接运行bazel test src/compiler/...该命令会验证grpc/src/compiler/下的各语言生成器BUILD 定义见 grpc/src/compiler/BUILD.bazel。运行 FlatBuffers gRPC 测试Linux先让动态链接器找到 gRPC 的共享库再运行测试export LD_LIBRARY_PATH$LD_LIBRARY_PATH:${GRPC_INSTALL_PATH}/lib make test ARGS-VARGS-V会以 verbose 模式输出每个测试用例的详细结果。以 grpctest.cpp 为例该测试覆盖了典型的 gRPC 集成场景服务端派生自生成的MonsterStorage::Service实现 Unary RPCStore用fbb_.ReleaseMessageStat()把MessageBuilder构建的响应所有权移交给 gRPC与 Server streaming RPCRetrieve通过writer-Write(monster)循环发送 5 条消息客户端通过grpc::CreateChannel(localhost:50051, grpc::InsecureChannelCredentials())连接并分别用MessageBuilder与普通FlatBufferBuilder各执行一次StoreRPC与RetrieveRPC当FLATBUFFERS_GRPC_DISABLE_AUTO_VERIFICATION未定义时还会构造一个无效请求断言 RPC 返回StatusCode::INTERNAL且错误消息为 “Message verification failed”验证 gRPC 消息自动校验机制。Bazel 用户bazel test tests/...C Callback API 代码生成生成命令FlatBuffers 的 gRPC C 代码生成目前可选支持现代 gRPC Callback API。在现有Service与异步 mixin 之外同时生成CallbackService骨架的方式是让flatc同时携带--grpc与--grpc-callback-api两个选项flatc --cpp --grpc --grpc-callback-api your_service.fbs从源码看flatc解析到该选项后会在 idl_gen_grpc.cpp 中将其写入generator_parameters.generate_callback_api最终传递给 gRPC 侧的生成器——对应 cpp_generator.h 中Parameters结构体的bool generate_callback_api false字段默认关闭显式开启才生成。生成的 CallbackService开启该选项后生成的头文件会在宏保护下新增一个类原文档示例class YourService::CallbackService : public ::grpc::Service { /* reactor virtuals */ };该类的实际生成逻辑位于 cpp_generator.cc先输出#if defined(GRPC_CALLBACK_API_NONEXPERIMENTAL)保护宏再打印CallbackService的前向声明与类定义并声明每个 RPC 对应的 reactor 虚函数末尾以#endif // GRPC_CALLBACK_API_NONEXPERIMENTAL收尾保证旧版 gRPC 库下不产生破坏性变更。每种 RPC 形态映射到相应的 reactor 返回类型RPC 形态CallbackService 方法返回类型Unary::grpc::ServerUnaryReactor*Client streaming::grpc::ServerReadReactorRequest*Server streaming::grpc::ServerWriteReactorResponse*Bidi streaming::grpc::ServerBidiReactorRequest, Response*默认生成的方法实现返回nullptr需要在你的派生类中覆写并返回一个由你管理的 reactor 实例生命周期模式参考 gRPC 官方文档。若你的 gRPC 库早于稳定版回调 API 宏即不存在GRPC_CALLBACK_API_NONEXPERIMENTAL保护宏内的代码会被整体跳过不影响原有编译。使用该特性请确保构建基于较新的 gRPC1.38具体最低版本以 gRPC 仓库为准。仓库中提供了对应的编译期验证测试grpctest_callback_compile.cpp 在FLATBUFFERS_GENERATED_GRPC_CALLBACK_API与GRPC_CALLBACK_API_NONEXPERIMENTAL同时定义时派生一个CallbackServiceImpl : public MyGame::Example::MonsterStorage::CallbackService并实例化用于确认生成的服务端骨架可编译仅编译验证不执行任何 RPC。客户端 Callback Stubs当提供--grpc-callback-api时生成的 C 客户端 stub 会在原有的同步 / 通用异步风格之外新增基于原生回调 / reactor 的异步方法并由同一个宏保护。对每个名为Foo的 RPC生成的方法签名如下摘自原文档Unaryvoid async_Foo(::grpc::ClientContext*, const Request, Response*, std::functionvoid(::grpc::Status)); void async_Foo(::grpc::ClientContext*, const Request, Response*, ::grpc::ClientUnaryReactor*);Client streaming::grpc::ClientWriteReactorRequest* async_Foo(::grpc::ClientContext*, Response*, ::grpc::ClientWriteReactorRequest*);Server streaming::grpc::ClientReadReactorResponse* async_Foo(::grpc::ClientContext*, const Request, ::grpc::ClientReadReactorResponse*);Bidirectional streaming::grpc::ClientBidiReactorRequest, Response* async_Foo(::grpc::ClientContext*, ::grpc::ClientBidiReactorRequest, Response*);这些方法直接映射到原生 gRPC 回调 API 工厂如CallbackUnaryCall、ClientCallbackWriterFactory::Create等不会自行创建线程I/O 驱动需要按 gRPC 文档覆写相应的 reactor 回调。若构建使用的 gRPC 缺少非实验性宏这些符号将不会被生成从而保持向后兼容。客户端侧的编译期验证见 grpctest_callback_client_compile.cpp它通过static_assert检查Stub::async_StoreUnary 的函数形式与 reactor 形式、Stub::async_RetrieveServer streaming 的ClientReadReactor、Stub::async_GetMaxHitPointClient streaming 的ClientWriteReactor以及Stub::async_GetMinMaxHitPointsBidi 的ClientBidiReactor等成员函数指针是否存在属于纯编译期测试不发起实际 RPC。多语言示例与常见注意事项grpc/examples/下的 greeter 示例展示了同一种 schema 在多种语言中的落地方式grpc/examples/go/greeterGo 客户端与服务端grpc/examples/python/greeterPython 客户端与服务端grpc/examples/swift/GreeterSwift 实现grpc/examples/ts/greeterTypeScript 实现grpc/samples/greeterC 版含 Makefile。示例 schema 定义了一个典型的rpc_service见 grpc/examples/greeter.fbsnamespace models; table HelloReply { message:string; } table HelloRequest { name:string; } rpc_service Greeter { SayHello(HelloRequest):HelloReply; SayManyHellos(HelloRequest):HelloReply (streaming: server); }grpc/examples/README.md 记录了两种语言的已知问题值得在实际开发中留意Python由于 Python 端可能收到Bytes array或utf8 string服务端 / 客户端需要自行断言类型。例如在SayHello中应先通过HelloRequest.HelloRequest().GetRootAs(request, 0)解析再对字符串做reply.decode(UTF-8)编码处理更稳妥的做法是保证所有进出 Python 的请求都是Bytes array如hello_request bytes(builder.Output())Gopayload 的content-type必须设置为application/grpcflatbuffers例如.SayHello(ctx, b, grpc.CallContentSubtype(flatbuffers))。小结围绕 grpc/README.md本文完整覆盖了 FlatBuffers 与 gRPC 集成的三个层面构建CMake 的FLATBUFFERS_BUILD_GRPCTEST与两个路径变量或 Bazel 的bazel test、测试运行make test ARGS-V与LD_LIBRARY_PATH以及--grpc-callback-api带来的现代 C 回调式代码生成。其中 Callback API 部分既有生成代码的形态说明四种 RPC 映射的 reactor 类型、客户端四种async_*签名也有仓库中两份编译期测试作为落地验证。配合多语言 greeter 示例与已知问题清单你可以据此快速搭建基于 FlatBuffers 序列化的 gRPC 服务。【免费下载链接】flatbuffersFlatBuffers: Memory Efficient Serialization Library项目地址: https://gitcode.com/GitHub_Trending/fl/flatbuffers创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考