• protobuf学习


    参考了这篇文章:

    http://www.ibm.com/developerworks/cn/linux/l-cn-gpb/

    开发环境在我的线下开发机器的

    /home/work/data/code/protobuf_demo

    用jumbo安装的protobuf,安装目录在/home/work/.jumbo/

    安装命令

    jumbo search protobuf
    jumbo install protobuf

    装好后,写一个proto文件,放在/home/work/data/code/protobuf_demo/src/proto/messageName.proto 

    package lm;
    message helloworld
    {
        required int32     id = 1;  // ID
        required string    str = 2;  // str
        optional int32     opt = 3;  //optional field
    }

    用命令

    protoc -I=proto --cpp_out=src proto/messageName.proto 

    然后在src里面,写writer.cc文件

    #include "messageName.pb.h"
    #include <stdio.h>
    #include <stdlib.h>
    #include <fstream>
    #include <iostream>
    
    using namespace std;
    
    int main(void) {
            lm::helloworld msg;
            msg.set_id(101);
            msg.set_str("hello");
    
            fstream output("./log", ios::out|ios::trunc|ios::binary);

    return 0; }

    编译命令:

    export LD_LIBRARY_PATH=/home/work/.jumbo/lib/:$LD_LIBRARY_PATH
    /opt/compiler/gcc-4.8.2/bin/g++ -o writer writer.cc messageName.pb.cc -L/home/work/.jumbo/lib/ -lprotobuf -I/home/work/.jumbo/include/

    运行 ./writer之后,生成 ./log,内容:ehello

    再写reader.cc文件:

    #include "messageName.pb.h"
    #include <fstream>
    #include <iostream>
    
    using namespace std;
    
    void dumpMsg(const lm::helloworld &msg) {
            cout << msg.id() << endl;
            cout << msg.str() << endl;
    }
    
    int main(int argc, char* argv[]) {
    
      lm::helloworld msg;
    
      {
        fstream input("./log", ios::in | ios::binary);
        if (!msg.ParseFromIstream(&input)) {
          cerr << "Failed to parse address book." << endl;
          return -1;
        }
      }
    
      dumpMsg(msg);
    }

    编译命令(加上writer的)

    export LD_LIBRARY_PATH=/home/work/.jumbo/lib/:$LD_LIBRARY_PATH
    /opt/compiler/gcc-4.8.2/bin/g++ -o writer writer.cc messageName.pb.cc -L/home/work/.jumbo/lib/ -lprotobuf -I/home/work/.jumbo/include/
    /opt/compiler/gcc-4.8.2/bin/g++ -o reader reader.cc messageName.pb.cc -L/home/work/.jumbo/lib/ -lprotobuf -I/home/work/.jumbo/include/

    然后运行reader,得到

    101
    hello

    又加了一个新的例子,通过管道来进行数据的传输和连接。

    proto file:

    message AMessage {
            required int32 a = 1;
            optional int32 b = 2;
            optional string str = 3;
    }

    生成头文件命令:

    protoc -I=proto --cpp_out=src proto/amessage.proto
    # if no '-I=proto' added, .pb.h and .pb.cpp files will be added to src/proto, but in .pb.cpp the header file is proto/.pb.h, abnormal

    producer.cc

    #include<stdio.h>
    #include<stdlib.h>
    #include<iostream>
    
    #include"amessage.pb.h"
    
    using namespace std;
    
    int main(int argc,const char* argv[]) {
            AMessage msg;
            if(argc < 2) {
                    fprintf(stderr, "usage:amessage a [b] [str]
    ");
                    return 1;
            }
            msg.set_a(atoi(argv[1]));
    
            if(argc > 2) {
                    msg.set_b(atoi(argv[2]));
            }
    
            if(argc > 3) {
                    msg.set_str(argv[3]);
            }
    
            if (!msg.SerializeToOstream(&cout)) {
                    cerr << "Failed to write msg." << endl;
                    return -1;
            }
    
            return 0;
    }

    consumer.cc

    #include<stdio.h>
    #include<stdlib.h>
    #include<iostream>
    
    #include"amessage.pb.h"
    
    using namespace std;
    
    int main(int argc, const char* argv[]) {
    
            AMessage msg;
            if (!msg.ParseFromIstream(&cin)) {
                    cerr << "Failed to parse address book." << endl;
                    return -1;
            }
            cout << msg.a() << endl;
            cout << msg.b() << endl;
            cout << msg.str() << endl;
            return 0;
    }

    编译命令:

    export LD_LIBRARY_PATH=/home/work/.jumbo/lib/:$LD_LIBRARY_PATH
    
    /opt/compiler/gcc-4.8.2/bin/g++ -o producer producer.cc amessage.pb.cc -L/home/work/.jumbo/lib/ -lprotobuf -I/home/work/.jumbo/include/
    
    /opt/compiler/gcc-4.8.2/bin/g++ -o consumer consumer.cc amessage.pb.cc -L/home/work/.jumbo/lib/ -lprotobuf -I/home/work/.jumbo/include/

    通过管道测试:

    [src]$ ./producer 2 3 str | ./consumer 
    2
    3
    str
    [src]$ ./producer 2 3 abc | ./consumer 
    2
    3
    abc
    [src]$ ./producer 2 3 | ./consumer 
    2
    3
    
    [src]$ ./producer 2 | ./consumer 
    2
    0
    
    [src]$ ./producer | ./consumer 
    usage:amessage a [b] [str]
    [libprotobuf ERROR google/protobuf/message_lite.cc:123] Can't parse message of type "AMessage" because it is missing required fields: a
    Failed to parse address book.

    可以看出,对于optional的字段,接收方直接使用是可以的,会拿到默认值,int是0,str是空串。

    (另外,测试的时候,发现在终端没有看到输出。但是管道却能够读入。原因找到是因为protobuf编码,如果只有几个数字,输出会非常小,增加了string后能看到有输出)比如:

    [src]$ ./producer 2 3            
    [src]$ ./producer 2 3 a
    a[src]$ ./producer 2 3 abcdefghijk
    
    abcdefghijk[src]$ 
  • 相关阅读:
    MySQL数据库之WHERE条件语句
    MySQL数据库的简单操作指令之DML语言
    课程设计必备之数据库操作代码模板
    MySQL数据库之外键约束的简单理解
    pdf.js的使用
    javascript连连看
    数据库问题
    列表文字超出后,鼠标悬浮显示全部内容
    springboot component注入servecie
    点击列表 获取table tr td 下的input value
  • 原文地址:https://www.cnblogs.com/charlesblc/p/5910442.html
Copyright © 2020-2023  润新知