第一次使用protobuf,中间碰到了不少坑,记录下来,也希望能帮到别人
一、编译。
在编译这里就碰到了一个坑,我下载的最新版的protobuf源码里面,并没有包含vsprojects文件夹,最新版改用CMake编译了,我折腾了半天也没编译成功。
看了网上的文章的发表时间,猜测应该是老版本的源码里面有vs的工程,于是下载了2.6.1版本的源码,果然有vs工程。于是直接用VS2015打开,它会升级工程文件,打开之后,直接编译,OK,没问题。
我是直接编译了Win32和x64平台的Debug和Release版本,编译工具选择的是VS2015-Windows XP。 总共四份,保存起来,以免将来要用到了还得再重新来编译。
然后最好把release版的protoc.exe拷贝到C:\Windows目录下,这样就可以在cmd里面直接使用,不用再切换目录了。protoc.exe主要是后面用来编译proto文件生成消息代码的。
运行vsprojects文件夹下的脚本文件extract_includes.bat,运行后会在vsprojects目录下产生include文件夹,里面放的是Protocol Buffers的头文件。
二、使用
先设计自己的通信协议,写proto文件,然后用protoc.exe生成协议代码,并将生成的代码放到自己的工程目录下。
这是我的协议文件:
option optimize_for = LITE_RUNTIME;
message LoginReq {
required string username = 1;
required string version = 2;
}
enum LoginFailReason {
ERR_LOGIN_USER_ONLINE = 0;
ERR_LOGIN_CLIENT_VERSION = 1;
}
message LoginFail{
required LoginFailReason loginresult = 1;
}
message HeartBeat {
required string username = 1;
}
message QunfaContent {
required string text = 1;
repeated bytes images = 2;
}
enum ClientStatus {
STU_STANDBY = 0;
STU_SENDING = 1;
}
message StatusIndication {
required ClientStatus status = 1;
}
第一行的意思就是使用精简版的protobuf库,程序只需要链接libprotobuf-lite.lib就可以了,这样生成的可执行程序速度快,体积小。但是牺牲了protobuf提供的反射功能(反正我也不会用…)
然后写一个bat文件,调用protoc.exe生成目标代码:
protoc -I=./ --cpp_out=./ pbTcpMessage.proto
将生成的代码放到自己的工程目录下,并添加到工程里面。
重要的地方来了, 先把之前生成的protobuf头文件(include目录)里面的google文件夹也复制到工程目录下,然后打开工程属性-C/C++-常规-附加包含目录 里面添加上你放置的目录。
我看网上其它的文章都说要把include文件夹复制到VC的安装目录下,我觉得不太好,直接放在工程目录下会比较好一点,看个人喜好了。
然后把编译生成的lib文件也复制到工程目录下面,并在代码里面使用#pragma comment(lib, “目录”)指令链接库文件。比如:
#pragma comment(lib, “../../protocol/lib/Release/x86/libprotobuf-lite.lib”)
然后编译,你可能会碰到如下错误:
1.找不到protobuf的头文件。
这个时候要检查你的工程属性里面的目录设置是否正确。
2.即便目录都设置正确了,还是很可能会碰到这个错误:
google/protobuf/stubs/stl_util.h no such file or directory
找不到google/protobuf/stubs/stl_util.h这个头文件。
起初我以为我的目录设置错了,我把inlcude下的google文件夹都复制到了VC的安装目录下也不行。后来才发现,google/protobuf/stubs/里面根本就没有stl_util.h这个文件。于是我抱着试一试的心态在protobuf的源码里面找到了这个文件,把它复制了过来,ok,这个错误解决了。(我想吐槽下,谷歌的大神们也这么马虎吗?用他们自己提供的脚本生成的头文件都不全。。。)
3.MS_VER不匹配,XXX重定义、XXX找不到符号等的链接错误
这种错误很常见,相信经常使用开源库的人都能碰到。
首先要明确protobuf默认编译出来的是静态库,而且是动态链接到CRT库的。
自己的工程在链接protobuf的lib文件的时候,自己的工程所使用的平台(Win32/x64)、模式(Debug/Release)和链接CRT的方式(MD/MDD/MT/MTD)都要与protobuf库编译时使用的平台、模式和链接CRT方式相同。
只要确保以上的内容,就不会有链接错误了。