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

Posted 跨链技术践行者

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了rust下根据protobuf的消息名创建对象实例相关的知识,希望对你有一定的参考价值。

在C++里面, 我们可以根据一个消息的名称, 动态的创建一个实例

1

2

3

4

5

6

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文件

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

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工程的依赖

1

2

[dependencies]

proto = {version="^0", path="proto"}

 

这时候, 就可以在主工程里面使用proto了

1

2

3

4

5

6

7

8

9

10

11

12

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

以上是关于rust下根据protobuf的消息名创建对象实例的主要内容,如果未能解决你的问题,请参考以下文章

protobuf 库在消息实例化时抛出 FatalException

Protobuf 消息是不是独立于平台

如何在构建消息之前在 protobuf 中设置重复字段?

rust替换函数名

java protobuf如何从int创建ByteString

Rust编程语言入门之项目实例:- 命令行程序