精华内容
下载资源
问答
  • 赋值代替 protobuf CopyFrom()

    万次阅读 2019-04-04 17:54:13
    赋值代替 protobuf CopyFrom() 示例:Replace protobuf CopyFrom with assignment protobuf 生成的 C++ 代码中,因为 CopyFrom() 可以接受任何 Message 作为参数, 所以有可能在2个不同类型的消息之间复制。 void...

    用赋值代替 protobuf CopyFrom()

    示例:Replace protobuf CopyFrom with assignment

    protobuf 生成的 C++ 代码中,因为 CopyFrom() 可以接受任何 Message 作为参数,
    所以有可能在2个不同类型的消息之间复制。

      void CopyFrom(const ::google::protobuf::Message& from) final;
      void CopyFrom(const PlayerData& from);
    

    而赋值操作可以保证类型正确。

    class PlayerData : public ::google::protobuf::Message {
     public:
      ...
      inline PlayerData& operator=(const PlayerData& from) {
        CopyFrom(from);
        return *this;
      }
      #if LANG_CXX11
      inline PlayerData& operator=(PlayerData&& from) noexcept {
        ...
      }
      #endif
    

    类型不一致时编译会报错:

    error: no match for ‘operator=’ (operand types are ‘a::PlayerData’ and ‘a::HeroInfo’)
    

    发现自己用了多年的 CopyFrom() 都是错误的使用。

    展开全文
  • C++ protobuf 自定义数据类型的赋值

    千次阅读 2018-12-05 10:59:29
    对于C++ protobuf 自定义数据类型的赋值,有两种方式 set_allocate_XXX mutable_XXX 举例说明 message SAT_JSON_CONFIG { required int32 AxisYMax = 1; required int32 AxisYMin = 2; } message SAT_GET_SAT_...

    对于C++ protobuf 自定义数据类型的赋值,有两种方式

    1. set_allocate_XXX
    2. mutable_XXX
      举例说明
    message SAT_JSON_CONFIG
    {
    required int32 AxisYMax 	= 1;
    required int32 AxisYMin 	= 2;
    }
    message SAT_GET_SAT_CONFIG_RSP
    {
    required  SAT_JSON_CONFIG satJsonConfig = 1;
    }
    

    方法一

    //系统会自动释放空间,不需要手动delete
    SAT_JSON_CONFIG *p_SatJsonConfig = new SAT_JSON_CONFIG();
    //给SAT_JSON_CONFIG赋值
    GetJsonFile(p_SatJsonConfig);
    //创建SAT_GET_SAT_CONFIG_RSP ,系统分配空间
    SAT_GET_SAT_CONFIG_RSP *p_SatGetSatConfigRsp = m_NetMsg.mutable_satgetsatconfigrsp();
    //赋值给系统分配的空间
    p_SatGetSatConfigRsp->set_allocated_satjsonconfig(p_SatJsonConfig);
    

    方法二

    //创建SAT_GET_SAT_CONFIG_RSP ,系统分配空间
    SAT_GET_SAT_CONFIG_RSP *p_SatGetSatConfigRsp = netMsg.mutable_satgetsatconfigrsp();
    //创建SAT_JSON_CONFIG , 系统分配空间
    SAT_JSON_CONFIG *p_SatJsonConfig = p_SatGetSatConfigRsp->mutable_satjsonconfig();
    //给SAT_JSON_CONFIG赋值
    GetJsonFile(p_SatJsonConfig);
    
    展开全文
  • 通过方法调用给ProtoObject赋值 Protobuf3 读取JSON 给ProtoObject 赋值
    展开全文
  • 服务器protobuf版本,3.0.0 本地pc的protobuf版本,3.0.0 使用python的requests库做接口自动化测试,首先尝试登陆自动化。 UserLogin.proto的文件内容如下 ![图片说明]...
  • 此文主要是总结,python使用protobuf的过程,如何序列化和反序列化,对不同类型的字段如何进行赋值

    前言

    使用protobuf主要是两个步骤,序列化和反序列化

    关于Proto有哪些数据类型,然后如何编写,此处就不赘述了,百度一下有很多。

    此文主要是总结,python使用protobuf的过程,如何序列化和反序列化,对不同类型的字段如何进行赋值。

    在本文最后,给出了一个本文的示例接口,你可以试试请求接口,体验一下gRPC的传输方式。

    序列化

    下面将一一列举各数据类型,在python中如何正确赋值,赋值后如何序列化。

    首先,得把编译包给导入

    import test_pb2 as pb
    

    我分为两部分,分别为未被repeated修饰的字段 和 被repeated修饰后的字段

    无修饰符

    字符串

    test.proto

    message SearchService {
    
        string type = 1;
    
    }
    

    创建message对象,然后赋值即可。与python中,通过类创建实例,实例.属性的方式进行赋值类似

    search_service = pb.SearchService()
    search_service.type = "request"
    

    数字型

    test.proto

    message SearchService {
    
        int32 id = 2;
    
    }
    

    与字符串赋值一致

    search_service = pb.SearchService()
    search_service.id = 1
    

    Message

    test.proto

    message SearchService {
    
        // 定义一个message类型
        message SearchRequest {
        
            string content = 1;
            
            string keyword = 2;
        
        }
        
        //   类型         字段名       序号
        SearchRequest searchRequest = 3;
    
    }
    

    我们看到在SearchService里序号为3的字段的类型为SearchRequest,这是我们新定义的message

    如果把message看作是一个类,那么我将其实例化,然后赋值给对应的字段,可以吗?

    ok,这是不行的,错误示例:

    search_service = pb.SearchService()
    # 实例化SearchRequest
    search_request = pb.SearchService.SearchRequest()
    # 为search_request内部字段赋值
    search_request.content = "hello protobuf"
    search_request.keyword = "mk"
    # 为search_service的searchRequest字段赋值
    search_service.searchRequest = search_request
    

    image-20210116211914264

    不允许在协议消息对象中分配复合字段“searchRequest”。

    正确示例:

    import test_pb2 as pb
    
    search_service.searchRequest.content = "hello protobuf!"
    search_service.searchRequest.keyword = "mk"
    

    如果加上之前的那个字段,那么这样的:

    import test_pb2 as pb
    
    search_service.type = "request"
    search_service.id = 1
    search_service.searchRequest.content = "hello protobuf!"
    search_service.searchRequest.keyword = "mk"
    

    Enum

    枚举类型,注意一点:必须包含一个含0的字段

    在这里插入图片描述

    test.proto

    syntax = "proto3";
    
    message SearchService {
    
        enum SearchType {
    
            A = 0;
    
            B = 1;
            
        }
    
        SearchType searchType = 4;
    
    }
    

    序号为4,类型为SearchType的枚举类,名为searchType的字段

    此处的枚举类型,你可以看作是网页中的单选框,只能从给定的数据中选择一个,不选则默认为0

    # 手动选择1
    search_service.searchType = 1
    
    # 或者是根据字段名进行选择
    search_service.searchType = pb.SearchService.SearchType.A
    

    被repeated修饰的字段

    字符串或数字

    test.proto

    syntax = "proto3";
    
    message SearchService {
        
        # 修饰符  类型  字段名 序号
        repeated int32 uid = 5;
        
    }    
    

    uid的类型是int32,然后被repeated修饰,即这个字段是可重复赋值的。

    那么,在python中应该怎么赋值呢?

    错误示例:

    search_service.uid = 0
    

    如果还是和之前一样的赋值,就会报错

    AttributeError: Assignment not allowed to repeated field “uid” in protocol message object.

    正确示例:

    search_service.uid.append(1)
    search_service.uid.append(2)
    

    所以,你可以将被repeated修饰的字段看作是一个空列表,往里添加值即可!

    Message

    test.proto

    syntax = "proto3";
    
    message SearchService {
        
        message Second {
            
            string type = 1;
            
            string word = 2;
            
        }
        
        repeated Second seconds = 6;
        
    }    
    

    seconds字段是可重复的message类型,在python中该如何赋值?

    # 实例化一个second
    second = search_service.Second()
    # 为second对象赋值
    second.type = 'abc'
    second.word = 'world'
    # 添加至seconds列表中
    search_service.seconds.append(second)
    

    或者,你也可以这样

    search_service.seconds.append(
        search_service.Second(type='efg', word="world")
    )
    

    或者这样:

    seconds = [
        search_service.Second(type='1', word="world"),
        search_service.Second(type='2', word="world")
    ]
    search_service.seconds.extend(seconds)
    

    所以,repeated修饰的字段,在python中,就是一个列表

    Enum

    test.ptoto

    syntax = "proto3";
    
    message SearchService {
        
        enum SortOrder {
            
            key1 = 0;
            
            key2 = 1;
            
            key3 = 2;
            
        }
        
        repeated SortOrder sortOrder = 7;
        
    }
    

    使用方法与之前的完全一致

    sortFields = [
        # 此处key1 根据关键词,获取枚举值
        search_service.SortOrder.key1,
        search_service.SortOrder.key2
    ]
    search_service.sortOrder.extend(sortFields)
    

    现在我们已经全部赋值好了,接着就是序列化了

    b = search_service.SerializeToString()
    
    print(b)
    
    # b'\n\x07request\x10\x01\x1a\x15\n\x0fhello protobuf!\x12\x02mk 
    # \x02*\x02\x01\x022\x0c\n\x03abc\x12\x05world2\x0c\n\x03efg
    # \x12\x05world2\n\n\x011\x12\x05world2\n\n\x012\x12\x05world:\x02\x00\x01'
    

    SerializeToString

    Serializes the protocol message to a binary string.

    序列化此协议消息为二进制串

    反序列化

    现在,我们是接收方,我们收到了一串二进制。

    首先,我们需要使用将其反序列化,同样使用编译包。

    search_service = pb.SearchService()
    b = b'\n\x07request\x10\x01\x1a\x15\n\x0fhello protobuf!\x12\x02mk \x02*\x02\x01\x022\x0c\n\x03abc\x12\x05world2\x0c\n\x03efg\x12\x05world2\n\n\x011\x12\x05world2\n\n\x012\x12\x05world:\x02\x00\x01'
    search_service.ParseFromString(b)
    # 访问属性值
    print(search_service.type) # 输出:request
    

    ParseFromString解析函数

    此时,search_service就已经含有传输过来的全部数据了。如果你不想使用对象.属性的方式调用,或者想使用类似json.loads直接转为python中的字典,那么你可以使用protobuf_to_dict将其转为字典。

    安装protobuf3_to_dict`

    pip install protobuf3_to_dict
    
    # 调用
    from protobuf_to_dict import protobuf_to_dict 
    
    b = b'\n\x07request\x10\x01\x1a\x15\n\x0fhello protobuf!\x12\x02mk \x02*\x02\x01\x022\x0c\n\x03abc\x12\x05world2\x0c\n\x03efg\x12\x05world2\n\n\x011\x12\x05world2\n\n\x012\x12\x05world:\x02\x00\x01'
    search_service.ParseFromString(b)
    # print(search_service.type)
    d = protobuf_to_dict(search_service)
    print(d, type(d))
    
    # {'type': 'request', 'id': 1, 'searchRequest': {'content': 'hello protobuf!', 'keyword': 'mk'}, 'searchType': 2, 'uid': [1, 2], 'seconds': [{'type': 'abc', 'word': 'world'}, {'type': 'efg', 'word': 'world'}, {'type': '1', 'word': 'world'}, {'type': '2', 'word': 'world'}], 'sortOrder': [0, 1]} <class 'dict'>
    

    小小尝试

    本文中例子,我做了一个接口。

    接口地址: http://47.101.154.110:8000/

    请求头请求体请求方式
    必须指定Content-Type: application/grpc-web+proto序列化后的二进制POST

    你可以使用postman提交数据,来查看结果

    在这里插入图片描述

    也可以使用Python发送请求

    import requests
    
    headers = {
        'Content-Type': 'application/grpc-web+proto'
    }
    
    b = b'\n\x07request\x10\x01\x1a\x15\n\x0fhello protobuf!\x12\x02mk \x02*\x02\x01\x022\x0c\n\x03abc\x12\x05world2\x0c\n\x03efg\x12\x05world2\n\n\x011\x12\x05world2\n\n\x012\x12\x05world:\x02\x00\x01'
    
    resp = requests.post('http://47.101.154.110:8000/', data=b, headers=headers)
    
    print(resp.text)
    

    完整的test.proto

    syntax = "proto3";
    
    message SearchService {
    
        string type = 1;
    
        int32 id = 2;
    
        // 定义一个message类型
        message SearchRequest {
        
            string content = 1;
            
            string keyword = 2;
        
        }
        
        //   类型         字段名       序号
        SearchRequest searchRequest = 3;
    
        enum SearchType {
    
            A = 0;
    
            B = 1;
    
        }
    
        SearchType searchType = 4;
    
        repeated int32 uid = 5;
    
        message Second {
    
            string type = 1;
    
            string word = 2;
    
        }
    
        repeated Second seconds = 6;
    
        enum SortOrder {
    
            key1 = 0;
    
            key2 = 1;
    
            key3 = 2;
    
        }
    
        repeated SortOrder sortOrder = 7;
    
    }
    

    完整的赋值示例

    import test_pb2 as pb
    from protobuf_to_dict import protobuf_to_dict
    
    
    search_service = pb.SearchService()
    
    
    search_service.type = "request"
    search_service.id = 1
    search_service.searchRequest.content = "hello protobuf!"
    search_service.searchRequest.keyword = "mk"
    # search_service.searchType = pb.SearchService.SearchType.A
    search_service.searchType = 2
    
    search_service.uid.append(1)
    search_service.uid.append(2)
    
    second = search_service.Second()
    second.type = 'abc'
    second.word = 'world'
    search_service.seconds.append(second)
    
    search_service.seconds.append(search_service.Second(type='efg', word="world"))
    
    seconds = [
        search_service.Second(type='1', word="world"),
        search_service.Second(type='2', word="world")
    ]
    search_service.seconds.extend(seconds)
    
    sortFields = [
        search_service.SortOrder.key1,
        search_service.SortOrder.key2
    ]
    search_service.sortOrder.extend(sortFields)
    
    
    b = search_service.SerializeToString()
    
    print(b)
    

    推荐模块

    在使用编译包时,没有代码提示,还有点不习惯。

    这里,推荐安装mypy-protobuf

    pip install mypy-protobuf
    

    使用方法:

    在你使用protoc命令编译proto文件时,新增一个参数mypy-out=,就像这样

    protoc --python_out=. --mypy-out=. test.proto
    

    此时会生成两个文件,并将他们拖入项目中的同一目录

    test_pb2.py:我们需要导入使用的编译包

    test_pb2.pyi:存根文件,在编辑器中会有代码提示(想了解存根文件,可以看最下面的参考文章)

    效果演示:

    演示

    参考文章

    https://github.com/dropbox/mypy-protobuf

    pyi文件是干嘛的?(一文读懂Python的存根文件和类型检查)

    展开全文
  • const google::protobuf::Descriptor* descriptor = google::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName(typeName); if (descriptor) { /* generated_factory():获取一个Message...
  • 1.给repeated类型的变量赋值 1.1 逐一赋值 定义protobuf结构如下: message Person { required int32 age = 1; required string name = 2; } message Family { repeated Person person = 1; } 对person进行赋值...
  • protobuf

    2019-07-29 12:01:31
    参考链接: ...一.背景介绍 protobuf用来做什么的 protobuf是谷歌开源的一个项目,是用来保存格式化的一些数据,或者用来定义网络通信的数据格式,全名叫protocol b...
  • Protobuf

    2021-04-07 18:54:34
    一.简介 protocol buffers 是一种语言无关、平台无关、可扩展的序列...Protobuf 提供了C++、java、python语言的支持,提供了windows(proto.exe)和linux平台动态编译生成proto文件对应的源文件。proto文件定义了协议数据
  • 使用protobuf,各功能号会不断增加,message也会一直变,我做为测试人员,需要做一个测试工具,前期可以通过mfc画图,就是画出message的各个属性对应的输入框,之后按照格式,遍历对应的message,读取输入框的数据来...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,236
精华内容 1,694
关键字:

protobuf赋值