文章開頭放一下IBM的google protocol buffer的介紹連接。http://www.ibm.com/developerworks/cn/linux/l-cn-gpb/linux
對於這種技術不斷更新的東西,我只能這麼理解:由於技術在更新,版本在變化,以前很詳盡的技術博文可能在以後的版本中遇到沒法預知的問題,因此咱們在使用時要注意甄別。廢話很少說,進入正文部分。ios
安裝什麼的都是小問題了,仍是貼一下步驟吧。c++
tar -xzf protobuf-2.5.0.tar.gz cd protobuf-2.5.0 ./configure --prefix=$INSTALL_DIR make make check make install
很簡單的標準*nix的安裝方法。隨後將安裝目錄的bin目錄下的protoc建立一個軟鏈接到/usr/bin目錄下便可。redis
隨後能夠進行簡單的例子測試了。我這裏有一個測試例子:函數
file:base.taskinfo.proto工具
package base; message funcinfo { required string funchandle = 1;//處理函數列表 optional string funcinit = 2; //初始化函數 optional string funcclean = 3; //清理函數 } message taskinfo { required int32 taskid = 1; //任務id required int32 pidcount = 2; //進程數目 required string filepath = 3; //輸入文件路徑 required string filename = 4; //文件名 required string temppath = 5; //臨時文件路徑 required string scriptpath = 6; //腳本路徑 required funcinfo func = 7; //函數信息 required string redisconn = 8; //redis連接ip及port }
而後用它來生成c++類型的相對應的文件:protoc --cpp_out=./ base.taskinfo.proto測試
就生成了兩個標準c++的頭文件和源文件:base.taskinfo.pb.cc base.taskinfo.pb.hui
而後就能夠寫簡單的例子進行測試了,這裏寫了一個叫write.cpp的簡單例子:(如下****部分涉及我的隱私,避免被人肉)this
#include "base.taskinfo.pb.h" #include <iostream> #include <fstream> using namespace std; int main() { base::funcinfo func; func.set_funchandle("GetKeyVal"); base::taskinfo msg1; msg1.set_taskid(1); msg1.set_pidcount(3); msg1.set_filepath("/data/home/****/data/basetest/indir"); msg1.set_filename("CH_PW_WAY"); msg1.set_temppath("/data/home/****/data/basetest/tmpdir"); msg1.set_scriptpath("/data/home/****/data/basetest/perl/CH_PW_WAY.pl"); msg1.set_allocated_func(&func); msg1.set_redisconn("10.200.25.155:7379"); fstream output("./log", ios::out | ios::trunc | ios::binary); if (!msg1.SerializeToOstream(&output)) { cerr<<"Failed to write msg."<< endl; return -1; } return 0; }
而後就能夠寫個Makefile去編譯這1個cpp,1個cc和1和h文件(protoc生成的.cc文件)google
#makefile by **** #2015年1月4日09:07:28 cc = g++ cpp = -fPIC -Wall -g inc += -I./ inc += -I/soft/protobuf-2.5.0/include libs += -L/soft/protobuf-2.5.0/lib -lprotobuf -lpthread objs=$(patsubst %.cc,%.o, $(wildcard *.cc)) objs+=$(patsubst %.cpp,%.o, $(wildcard *.cpp)) %.o:%.cc $(cc) $(cpp) $(inc) -o $@ -c $< @echo "$@" %.o:%.cpp $(cc) $(cpp) $(inc) -o $@ -c $< @echo "$@" module=./writer all:$(module) $(module):$(objs) $(cc) $(cpp) $(inc) -o $(module) $^ $(libs) @echo "$@" clean: @rm -f $(objs) $(module) @echo "clean done."
編譯沒問題,而後很快樂的就生成了可執行文件
隨後就是 執行,讓他生成log文件就好了,執行的時候出現了沒法找到lib的錯誤,好吧,把剛纔的安裝目錄下的lib目錄添加到環境變量$LD_LIBRARY_PATH中去,再執行就出現了:
*** glibc detected *** ./writer: munmap_chunk(): invalid pointer: 0x00007fff8521b9b0 ***
======= Backtrace: =========
/lib64/libc.so.6(+0x75358)[0x7fa138d93358]
./writer[0x4046f1]
./writer[0x403732]
./writer[0x4044ae]
./writer[0x409010]
/lib64/libc.so.6(__libc_start_main+0xe6)[0x7fa138d3cc36]
./writer[0x403099]
======= Memory map: ========
..如下省略數千個字符。總之就是core掉了。試試gdb工具,調試結果以下所示:
Missing separate debuginfo for /lib64/ld-linux-x86-64.so.2 Try: zypper install -C "debuginfo(build-id)=c81de241a528795f8dbfde0f0e0e236f9a6554e6" Core was generated by `./writer'. Program terminated with signal 6, Aborted. #0 0x00007fad42931b55 in raise () from /lib64/libc.so.6 (gdb) bt #0 0x00007fad42931b55 in raise () from /lib64/libc.so.6 #1 0x00007fad42933131 in abort () from /lib64/libc.so.6 #2 0x00007fad4296ec2f in __libc_message () from /lib64/libc.so.6 #3 0x00007fad42974358 in malloc_printerr () from /lib64/libc.so.6 #4 0x00000000004046e1 in base::funcinfo::~funcinfo (this=0x7fff3026a2c0, __in_chrg=<optimized out>) at base.taskinfo.pb.cc:167 #5 0x0000000000403722 in base::taskinfo::SharedDtor (this=0x7fff3026a270) at base.taskinfo.pb.cc:537 #6 0x000000000040449e in base::taskinfo::~taskinfo (this=0x7fff3026a270, __in_chrg=<optimized out>) at base.taskinfo.pb.cc:517 #7 0x0000000000409000 in main () at writer.cpp:25
應該是析構函數出錯了,看一下到底protoc給咱們生成了什麼東西吧。這段代碼摘自base.taskinfo.pb.cc
void taskinfo::SharedDtor() { if (filepath_ != &::google::protobuf::internal::kEmptyString) { delete filepath_; } if (filename_ != &::google::protobuf::internal::kEmptyString) { delete filename_; } if (temppath_ != &::google::protobuf::internal::kEmptyString) { delete temppath_; } if (scriptpath_ != &::google::protobuf::internal::kEmptyString) { delete scriptpath_; } if (redisconn_ != &::google::protobuf::internal::kEmptyString) { delete redisconn_; } if (this != default_instance_) { delete func_; } }
我擦。(請原諒個人粗魯),竟然是delete func_,我頓時就不能淡定了。我申請的是棧內存,你給我來個delete,不core纔怪了~好吧,請原諒我沒有看你這個生成的1061行的源代碼。
改一下上面的write.cpp的代碼:
#include "base.taskinfo.pb.h" #include <iostream> #include <fstream> using namespace std; int main() { base::funcinfo *func = new base::funcinfo(); func->set_funchandle("GetKeyVal"); base::taskinfo *msg1 = new base::taskinfo(); msg1->set_taskid(1); msg1->set_pidcount(3); msg1->set_filepath("/data/home/****/data/basetest/indir"); msg1->set_filename("CH_PW_WAY"); msg1->set_temppath("/data/home/****/data/basetest/tmpdir"); msg1->set_scriptpath("/data/home/****/data/basetest/perl/CH_PW_WAY.pl"); msg1->set_allocated_func(func); msg1->set_redisconn("10.200.25.155:7379"); fstream output("./log", ios::out | ios::trunc | ios::binary); if (!msg1->SerializeToOstream(&output)) { cerr<<"Failed to write msg."<< endl; return -1; } return 0; }
好 編譯運行沒問題了,都解決了。生成了一個log文件,這文件沒辦法看了。內容按照他本身的格式寫的,有一些亂碼和一些能看得懂的,本身寫進去的東西。