从零开始构建 Google Protocol Buffer / protobuf 的helloworld工程
从零开始构建 Protocol Buffer / protobuf 的helloworld工程
PS:若懒得看正文,文末提供了本文所述过程生成的VS工程的下载链接,可直接下载使用。
前言
1. 下载protobuf
下载地址: https://github.com/protocolbuffers/protobuf/releases
当前最新版本为3.19.0,在下载页面中直接下载protobuf-cpp-3.19.0.zip
注意:
若不想自己编译,想下载项目编译好的release文件时,在将protobuf引入自己的工程后,再编译时会提示缺少文件。
报错信息为:
fatal error C1083: 无法打开包括文件: “google/protobuf/port_def.inc”: No such file or directory
实际去protoc-3.19.0-win64.zip 的解压目录的include 文件夹下看,确实也不存在对应文件。protoc-3.19.0-win64.zip 压缩包中的include 文件夹与protobuf-cpp-3.19.0.zip 源码相比,也确实少了一些文件。
因此最终还是得下载源码自行编译,在源码的src目录中有相关文件。
下载地址 https://cmake.org/download/
当前最新版本为3.22.0,在下载页面中直接下载cmake-3.22.0-rc1-windows-x86_64.zip
protobuf-cpp-3.19.0.zip 需要使用cmake生成vs工程,因此需要下载cmake工具。
若自己电脑上原来已经有cmake工具,可不下载,用自己电脑上的cmake工具即可。
2. cmake生成protobuf工程
解压cmake-3.22.0-rc1-windows-x86_64.zip 后,运行cmake-gui.exe 在弹出窗口中按如下步骤操作。(在下述例子中,protobuf解压后的目录为E:/TestProj/protobuf-cpp-3.19.0 )
在红色背景框区域可更改默认生成配置,更改完成后点击Configure 按钮更新配置,随后点击Generate 按钮生成vs工程。
在最后一步可直接单击Open Project 按钮,cmake可直接调用VS2017打开protobuf的VS解决方案工程文件。
也可以自己去E:\TestProj\protobuf-cpp-3.19.0\build 目录用VS2017 打开protobuf.sln 文件。
3. vs编译protobuf工程
在打开的protobuf工程中分别编译 libprotobuf 和protoc 这两个项目。(其他项目编译与否,请看自己的实际情况)。正常情况下,仅编译 libprotobuf 和protoc 两个项目已经可以满足核心需要。
- 以debug为例,生成一下文件:libprotobufd.lib、libprotocd.lib和protoc.exe
debug版本生成的文件如下图
- 以release为例,生成一下文件:libprotobuf.lib、libprotoc.lib和protoc.exe
release版本生成的文件如下图
4. 编写项目自己的.proto文件
.proto 文件的语法请查看其它blog或者查看官方指南 https://developers.google.com/protocol-buffers/docs/proto3
在本案例中以proto3 为helloworld案例。proto2 的案例请自行修改。
// helloworld.proto
syntax = 'proto3';
package hellopb;
message helloworld
{
int32 id = 1; // ID
string str = 2; // str
}
解释:
定义了一个package 名字叫做 hellopb,对应C++的namespace
定义了一个消息名称为 helloworld 的消息类型,该消息有2个成员,类型为 int32 的 id,另一个为类型为 string 的成员 str。
使用protoc.exe 对消息进行处理,生成C++编译器可识别的.h 和.cc 文件
生成命令如下:(在使用时要注意.exe和.proto文件的路径)。
protoc.exe -I=. --cpp_out=. ./helloworld.proto
不知道 proto.exe的参数含义时,可使用 protoc.exe --help 命令查看帮助文档。
可参照下图:
5. 将protobuf引入自己的工程
此处以Debug版本为例
-
生成helloworld工程 使用vs2017自己生成一个helloworld测试工程。 -
拷贝依赖项 将生成的libprotobufd.lib、libprotocd.lib和protoc.exe 文件拷贝至项目的lib目录。(注意:本文使用的是静态库,若需要动态库,则需在cmake阶段选择生成dll动态库) -
拷贝头文件 将源码E:\TestProj\protobuf-cpp-3.19.0\protobuf-3.19.0\src 下的google 文件夹拷贝至helloworld项目的include 文件夹
文字说明:
[配置属性]->[C/C++]->[常规]->[附加包含目录] : 添加google 文件夹所在路径,默认在项目的include下
[配置属性]->[连接器]->[常规]->[附加库目录] : 添加libprotobufd.lib 和libprotocd.lib 文件所在路径
[配置属性]->[连接器]->[输入]->[附加依赖项] :添加 libprotobufd.lib 和libprotocd.lib
直接在需要写消息的cpp文件中 #include “helloworld.pb.h”
也可按下述例图进行配置。
项目文件目录
文件拷贝后的目录为:
解决方案
修改附加包含目录
修改附加库目录
修改附加依赖项
// main.cpp
#include <iostream>
#include <fstream>
#include "msg/helloworld.pb.h"
int main(int argc, char* argv[])
{
hellopb::helloworld msgwrite;
msgwrite.set_id(1001);
msgwrite.set_str("hello world");
char buff[1024] = { 0 };
msgwrite.SerializeToArray(buff, 1024);
hellopb::helloworld msgread;
msgread.ParseFromArray(buff, 1024);
std::cout << "id:" << msgread.id() << std::endl;
std::cout << "str:" << msgread.str() << std::endl;
}
运行后输出为:
id:1001
str:hello world
注意事项
Q:若在添加依赖项和库后进行编译时报出错误 error LNK2038
1>------ 已启动生成: 项目: ProtocolBuf, 配置: Debug x64 ------
1>libprotobufd.lib(arenastring.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MTd_StaticDebug”不匹配值“MDd_DynamicDebug”(main.obj 中)
1>libprotobufd.lib(message_lite.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MTd_StaticDebug”不匹配值“MDd_DynamicDebug”(main.obj 中)
1>libprotobufd.lib(common.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MTd_StaticDebug”不匹配值“MDd_DynamicDebug”(main.obj 中)
... ...
A:
此问题是因为在protobuf.sln 下编译libprotobuf 和protoc 两个项目的工程属性中的运行时库与helloworld工程的运行时库不一致导致的,将两者运行时库修改为一致即可。
修改路径为:[配置属性]->[C/C++]->[代码生成]->[运行库]
libprotobuf 和protoc 项目的工程属性默认运行时库为:
Debug : 多线程调试 (/MTd)
Release:多线程 (/MT)
本文中所述的项目资源已上传至CSDN,可按需下载。 该工程包含了x86/x64的Debug/Release 共计4个版本,且均编译通过,可拿来即用。 下载链接: google protobuf 初学者 helloworld VS2017 + protobuf-3.19.0 工程示例
|