Rust Protocol Buffers代码生成插件protoc-gen-prost-crate的使用,高效生成类型安全gRPC和Protobuf Rust代码
protoc-gen-prost-crate 完整示例
以下是基于提供内容的完整示例演示如何使用protoc-gen-prost-crate
生成Rust代码:
1. 安装protoc-gen-prost-crate
cargo install protoc-gen-prost-crate
2. 创建项目结构
my_proto_project/
├── proto/
│ └── greeter/
│ └── v1/
│ └── greeter.proto
└── buf.gen.yaml
3. greeter.proto文件内容
syntax = "proto3";
package greeter.v1;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloResponse);
}
message HelloRequest {
string name = 1; // 请求中包含的名字
}
message HelloResponse {
string message = 1; // 返回的问候消息
}
4. buf.gen.yaml配置
version: v1
plugins:
- plugin: prost
out: gen/src
opt:
- bytes=. # 生成字节数组支持
- file_descriptor_set # 生成文件描述符集
- plugin: prost-crate
out: gen
strategy: all # 使用all策略查看完整protobuf模式
opt:
- gen_crate # 生成Cargo crate
- only_include=.greeter # 只包含greeter包
5. 运行代码生成
cd my_proto_project
buf generate
6. 生成的文件结构
gen/
├── Cargo.toml
└── src
├── greeter.v1.rs # 生成的Rust protobuf代码
└── lib.rs # 包含文件和模块定义
7. 生成的Cargo.toml内容
[package]
name = "greeter-proto"
version = "0.1.0"
edition = "2021"
[dependencies]
prost = "0.10.0"
[features]
default = ["proto_full"]
## @@protoc_deletion_point(features)
## This section is automatically generated by protoc-gen-prost-crate.
## Changes in this area may be lost on regeneration.
proto_full = ["greeter-v1"]
"greeter-v1" = []
## @@protoc_insertion_point(features)
8. 生成的lib.rs内容
#[cfg(feature = "greeter-v1")]
pub mod greeter {
pub mod v1 {
include!("greeter.v1.rs"); // 包含生成的protobuf代码
}
}
9. 在项目中使用的示例
use greeter_proto::greeter::v1::{HelloRequest, HelloResponse};
fn main() {
let request = HelloRequest {
name: "World".to_string(),
};
println!("Sending request: {:?}", request);
}
关键点说明
-
多语言支持:这个工具特别适合在多语言环境中使用Protocol Buffers的情况
-
功能特性:
- 自动生成Cargo crate
- 支持条件编译功能标志
- 与buf工具链集成
-
代码组织:
- 生成的代码放在单独目录(gen/)
- 通过include!宏包含生成代码
- 保持生成代码与自定义代码分离
-
优势:
- 简化多语言项目的protobuf代码生成
- 自动管理功能标志和模块组织
- 与现有Protocol Buffers工具链良好集成
这个示例展示了如何从protobuf定义开始,通过protoc-gen-prost-crate生成完整的Rust crate,最后在项目中使用的完整流程。
1 回复
Rust Protocol Buffers代码生成插件protoc-gen-prost-crate使用指南
以下是基于您提供的内容整理的完整示例:
完整示例代码
项目结构
grpc-example/
├── proto/
│ └── greeter.proto
├── crates/
├── build.rs
└── Cargo.toml
proto/greeter.proto
syntax = "proto3";
package greeter;
service GreeterService {
rpc SayHello (HelloRequest) returns (HelloResponse);
}
message HelloRequest {
string name = 1;
}
message HelloResponse {
string message = 1;
int32 response_code = 2;
}
build.rs
// 设置构建脚本
fn main() -> std::io::Result<()> {
// 确保protoc编译器可用
std::env::set_var("PROTOC", protoc_bin_vendored::protoc_bin_path().unwrap());
// 配置代码生成参数
protoc_gen_prost_crate::run(protoc_gen_prost_crate::Args {
out_dir: "crates", // 输出目录
includes: &["proto"], // proto文件搜索路径
input: &["proto/greeter.proto"], // 输入proto文件
rustfmt: true, // 自动格式化生成的代码
default_package_filename: "grpc_api", // 默认包名
..Default::default()
})
}
Cargo.toml
[package]
name = "grpc-example"
version = "0.1.0"
edition = "2021"
[build-dependencies]
protoc-bin-vendored = "3.0.0" # 提供protoc编译器
protoc-gen-prost-crate = "0.3.0" # 代码生成插件
[dependencies]
grpc-api = { path = "crates/grpc-api" } # 生成的crate
tokio = { version = "1.0", features = ["full"] } # 异步运行时
tonic = "0.8" # gRPC框架
服务端实现 src/main.rs
use grpc_api::greeter_service_server::{GreeterService, GreeterServiceServer};
use grpc_api::{HelloRequest, HelloResponse};
use tonic::{Request, Response, Status};
// 实现GreeterService trait
#[derive(Debug, Default)]
pub struct MyGreeter;
#[tonic::async_trait]
impl GreeterService for MyGreeter {
async fn say_hello(
&self,
request: Request<HelloRequest>, // 接收请求
) -> Result<Response<HelloResponse>, Status> {
// 处理请求
let name = request.into_inner().name;
// 构建响应
let reply = HelloResponse {
message: format!("Hello, {}!", name),
response_code: 200,
};
Ok(Response::new(reply))
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// 设置服务地址
let addr = "[::1]:50051".parse()?;
let greeter = MyGreeter::default();
println!("Server listening on {}", addr);
// 启动gRPC服务
tonic::transport::Server::builder()
.add_service(GreeterServiceServer::new(greeter))
.serve(addr)
.await?;
Ok(())
}
客户端示例 src/client.rs
use grpc_api::greeter_service_client::GreeterServiceClient;
use grpc_api::HelloRequest;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// 创建客户端连接
let mut client = GreeterServiceClient::connect("http://[::1]:50051").await?;
// 准备请求
let request = tonic::Request::new(HelloRequest {
name: "Tonic".into(),
});
// 发送请求并获取响应
let response = client.say_hello(request).await?;
println!("RESPONSE={:?}", response.into_inner());
Ok(())
}
使用说明
- 首先安装所需工具:
cargo install protoc-gen-prost-crate
- 构建项目:
cargo build
- 运行服务端:
cargo run
- 在另一个终端运行客户端测试:
cargo run --bin client
关键点说明
- 自动生成的代码位于
crates/grpc-api
目录 - 服务实现只需关注业务逻辑,框架代码由插件自动生成
- 客户端和服务端共享相同的Protobuf定义,确保类型安全
- 项目会自动处理所有gRPC和Protobuf相关依赖
这个完整示例展示了如何使用protoc-gen-prost-crate从定义Protobuf文件到实现完整的gRPC服务的过程,涵盖了服务端和客户端的实现。