概述
本文内容包括:github上获取源码,用cmake生成工程并编译,简要介绍两种库分别在C++和C#工程中的使用方法。
protobuf
protobuf源码获取
protobuf源码的github地址:
https://github.com/google/protobuf.git
在releases中可以获取各版本压缩包。
下文采用git clone获取到3.7.x分支
克隆下来的仓库中包含两个子模块benchmark和googletest,位于third_party中,使用cmake编译进入到third_party目录,执行:
git submodule update --init --recursive
zlib获取和编译
用cmake编译protobuf源码时可能会报错:cmake Could NOT find ZLIB (missing: ZLIB_LIBRARY),我们提前准备好zlib。
下载:zlib-1.2.11.zip
github地址:https://github.com/madler/zlib/releases
进入目录/contrib/vstudio,找到对应版本的vs打开,例如进入vc10,用VS2010打开zlibvc.sln,然后编译zlibvc
编译生成32位Debug(位于x86\ZlibDllDebug\zlibwapid.lib)、32位Release(位于x86\ZlibDllRelease\zlibwapid.lib)、64位Debug(位于x64\ZlibDllDebug\zlibwapi.lib)和64位Release(位于x64\ZlibDllRelease\zlibwapi.lib)
使用cmake生成VS工程
安装cmake 64位,官方网站:https://cmake.org/download/ 下载:cmake-3.9.0-rc3-win64-x64.msi
打开cmake可视化界面,指定protobuf源码的cmake目录和protobuf工程生成目录,勾选Advanced
点击Configure,选择生成VS工程的版本,如下图
选择Visual Studio 15 2017即编译VS2017 win32工程,选择Visual Studio 15 2017 Win64即编译VS2017 win64工程。
若提示无法找到ZLIB,则在窗口中找到下图这三个变量名,设置值
ZLIB_INCLUDE_DIR即zlib源码路径
ZLIB_LIBRARY_DEBUG和ZLIB_LIBRARY_RELEASE分别对应上文编译好的库文件zlibwapid.lib和zlibwapi.lib(注意,若要生成VS win64工程要选择64位的库文件,VS win32工程则选择32位的库文件)
配置好以后,再次点击Configure,如下图:
下方输出栏打印“Configuring done”表示Configure成功,点击Generate,输出栏打印“Generating done”,此时在生成目录可以找到VS工程。
用VS工程编译protubuf
打开VS工程,选择Release Win32或Release Win64进行编译,在输出目录下生成下图protoc.exe及库文件。
受zlib某些因素影响,tests项目可能编译失败,无法生成tests.exe,但没有关系,对库的使用不构成影响
protobuf的使用示例
在protoc.exe所在目录创建一个文件夹作为生成文件夹,例如Generate,并创建一个dataClass.proto文件,写入以下内容:
syntax = "proto2";
message DataPackage{
repeated double real_array = 1; //实型数组
required int32 real_count = 2; //实型数组大小
repeated int32 int_array = 3; //整型数组
required int32 int_count =4; //整型数组大小
}
在当前位置打开命令窗口,输入命令:
.\protoc --cpp_out=Generate dataClass.proto
在Generate文件夹内生成了dataClass.pb.h和dataClass.pb.cc文件,将这两个文件加入到工程中,将proto源码目录protobuf_3.7.x/src添加到工程配置的附加包含目录,并将libprotoc.lib和libprotobuf.lib添加到附加依赖项中。
protobuf-net
protobuf-net工具获取
protobuf-net源码的Github地址如下:
https://github.com/mgravell/protobuf-net
可以选择直接克隆master分支,或者在release中获取发布出的版本,目前最新的release版本是2.3.5,地址为:
https://github.com/mgravell/protobuf-net/releases?after=2.3.11
该地址可以获取编译好的应用程序压缩包protogen.1.0.0.zip,也可以下载对应版本的源文件。下载protogen.1.0.0.zip并解压,其中包含一个Release文件夹,Release文件夹内容如下图所示。
进入到net40目录。
其中的protogen.exe就是根据*.proto文件生成*.cs文件的工具。
除此之外,还可以从GitHub上克隆master分支,在目录:
protobuf-net\src\protogen.site\wwwroot\protogen
下有多个版本的protogen压缩包,解压后目录结构与release中获取的protogen.1.0.0.zip一样。
或者根据源码自行编译处protogen.exe。
用 *.proto 生成 *.cs
下面用一个示例说明如何将*.proto转换为*.cs:
假设我的protogen.exe位于E:\protogen 1.0.0,如下图所示:
在此文件夹中创建一个文件“student.proto”,用记事本打开,添加内容:
message Student{
required string name = 1; //名称,字符串类型
required double gender = 2; //性别,bool类型(取值0或1)
required int32 age = 3; //年龄,整型
repeated double telephone =4; //电话号码,字符串数组
}
保存文件,在此文件夹中创建一个文件夹Generate作为输出文件夹,如图:
在当前位置打开cmd或powershell窗口,输入命令:
.\protogen --csharp_out=.\Generate student.proto
在Generate文件夹内生成.cs文件
附:proto语法
proto语法由proto2和proto3两个版本,以下内容适用于proto2
proto文件字段规则类型
required:表示后面的数据是必须的。
optional:表示后面数据是可选的。
repeated:表示后面的数据是一个数组。
proto文件标量数值类型
proto类型 | Java 类型 | C++类型 | 备注 |
---|---|---|---|
double | double | double | |
float | float | float | |
int32 | int | int32 | 使用可变长编码方式。编码负数时不够高效——如果你的字段可能含有负数,那么请使用sint32。 |
int64 | long | int64 | 使用可变长编码方式。编码负数时不够高效——如果你的字段可能含有负数,那么请使用sint64。 |
uint32 | int[1] | uint32 | Uses variable-length encoding. |
uint64 | long[1] | uint64 | Uses variable-length encoding. |
sint32 | int | int32 | 使用可变长编码方式。有符号的整型值。编码时比通常的int32高效。 |
sint64 | long | int64 | 使用可变长编码方式。有符号的整型值。编码时比通常的int64高效。 |
fixed32 | int[1] | uint32 | 总是4个字节。如果数值总是比总是比228大的话,这个类型会比uint32高效。 |
fixed64 | long[1] | uint64 | 总是8个字节。如果数值总是比总是比256大的话,这个类型会比uint64高效。 |
sfixed32 | int | int32 | 总是4个字节。 |
sfixed64 | long | int64 | 总是8个字节。 |
bool | boolean | bool | |
string | String | string | 一个字符串必须是UTF-8编码或者7-bit ASCII编码的文本。 |
bytes | ByteString | string | 可能包含任意顺序的字节数据。 |
关于proto文件的参考资料
官方文档
CSDN:proto3语法指南
CSDN:C# protobuf的使用方法
在C#工程中使用*.cs
只需要将上一步生成的myproto.cs加入到工程里,并且将protobuf-net.dll文件添加引用即可。
示例程序:(对上一步生成的student.cs文件的调用)
using ProtoBuf;
using System;
using System.IO;
namespace UnityUDPClient
{
class Program
{
static void Main(string[] args)
{
//实例化一个Student对象
Student yiya = new Student();
yiya.Name = "yiya";
yiya.Gender = 0;
yiya.Age = 30;
yiya.Telephones.Add("000");
yiya.Telephones.Add("111");
yiya.Telephones.Add("222");
//序列化
MemoryStream ms = new MemoryStream();
Serializer.Serialize(ms, yiya);
byte[] data_yiya = ms.ToArray();
//反序列化
MemoryStream ms1 = new MemoryStream(data_yiya);
Student yiya2 = Serializer.Deserialize(ms1);
Console.ReadKey();
}
}
}
在Unity(或其他C#项目)中使用 *.cs
将上一步生成的myproto.cs拷贝到Assets目录下,再将protobuf-net.dll拷贝到Assets下的Plugin文件夹。