• rust下根据protobuf的消息名创建对象实例


    在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

  • 相关阅读:
    APS.NET MVC + EF (14)---项目框架搭建
    APS.NET MVC + EF (11)---过滤器
    APS.NET MVC + EF (10)---使用AJAX
    APS.NET MVC + EF (06)---模型
    APS.NET MVC + EF (08)---数据注解和验证
    APS.NET MVC + EF (07)---表单和HTML辅助方法
    APS.NET MVC + EF (05)---控制器
    错误 1 error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏
    VS2010中项目配置引入GDAL
    Win7(32/64)VS2010配置编译GDAL环境(图文教程+亲测可用!)
  • 原文地址:https://www.cnblogs.com/egmkang/p/11481929.html
Copyright © 2020-2023  润新知