参考了这篇文章:
http://www.ibm.com/developerworks/cn/linux/l-cn-gpb/
开发环境在我的线下开发机器的
/home/work/data/code/protobuf_demo
用jumbo安装的protobuf,安装目录在/home/work/.jumbo/
安装命令
jumbo search protobufjumbo 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#include #include #include 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#include 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,得到
101hello
又加了一个新的例子,通过管道来进行数据的传输和连接。
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#include #include #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]\n"); 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#include #include #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 23str[src]$ ./producer 2 3 abc | ./consumer 23abc[src]$ ./producer 2 3 | ./consumer 23[src]$ ./producer 2 | ./consumer 20[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: aFailed to parse address book.
可以看出,对于optional的字段,接收方直接使用是可以的,会拿到默认值,int是0,str是空串。
(另外,测试的时候,发现在终端没有看到输出。但是管道却能够读入。原因找到是因为protobuf编码,如果只有几个数字,输出会非常小,增加了string后能看到有输出)比如:
[src]$ ./producer 2 3 [src]$ ./producer 2 3 aa[src]$ ./producer 2 3 abcdefghijkabcdefghijk[src]$