在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
在C++里面, 我们可以根据一个消息的名称, 动态的创建一个实例 google::protobuf::Descriptor* desc = google::protobuf::DescriptorPool::generated_pool() ->FindMessageTypeByName("mypkg.MyType"); google::protobuf::Message* message = google::protobuf::MessageFactory::generated_factory() ->GetPrototype(desc)->New(); 这个在protobuf里面是集成进去了, 在其他语言也有类似的东西.
通过这个, 我们就让轻松实现编解码库, 而不需去构造一个映射表.
但是, 但是在rust里面, 是没有这种东西的. 比较难的地方是rust全局变量必须要实现Send trait, 否则是不能被共享的, 这样做确实安全, 但是对于我们实现MessageFactory就变得困难. 好在rust有thread_local和build.rs, 我们可以通过build.rs在编译proto文件的时候去遍历, 把每个消息添加到一个thread_local的hash map里面去, 从而曲线救国. 不说实现细节, 可以自己去看源码, 这边说如何使用和集成.
1. 创建一个子工程, 名字叫proto 然后将依赖添加进去: [dependencies] protobuf = "2.8.0" [build-dependencies] protoc-rust = "2.8.0" protobuf_message_factory = "0.1.2" 2. 把所有的.proto文件都添加到src目录下面去 3. 添加一个build.rs文件 extern crate protobuf_message_factory; use protobuf_message_factory::*; ... fn main() { let proto_path = "src/"; let proto_files = get_protos_info(proto_path); let proto_messages = get_proto_list(&proto_files); //!!! this is importent. !!! protoc_rust::run(protoc_rust::Args { out_dir: proto_path, input: &protos, includes: &[proto_path], customize: Customize { ..Default::default() }, }).expect("protoc"); //now generate factory codes generate_factory_file(proto_path, &proto_files); } 然后把build.rs添加到toml里面去 4. 到主工程里面去, 添加对proto工程的依赖 [dependencies] proto = {version="^0", path="proto"}
这时候, 就可以在主工程里面使用proto了 extern crate proto; use proto::factory::*; use proto::rpc::*; use local_ipaddress; fn main() { let desc = get_descriptor("mypkg.MyType".to_string()).unwrap(); println!("{}", desc.full_name()); let msg = desc.new_instance(); println!("msg: {:?}", msg); }
cargo run: 就可以看到 mypkg.MyType msg:
这时候就可以拿到MessageDesriptor, 通过这个对象可以new一个instance
仓库在这里https://crates.io/crates/protobuf_message_factory
关键字: MessageFactory, Protobuf, Rust |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论