标签 protobuf 下的文章

“”

protobuf 交叉编译 for arm

github 地址:https://github.com/protocolbuffers/protobuf

下载最新版3.17.3

wget https://github.com/protocolbuffers/protobuf/archive/refs/tags/v3.17.3.zip
mv v3.17.3.zip protobuf-v3.17.3.zip
unzip protobuf-v3.17.3.zip
cd protobuf-3.17.3/
./autogen.sh 
CC=arm-linux-gnueabihf-gcc CXX=arm-linux-gnueabihf-g++ ./configure --prefix=$(pwd)/install --host=arm-linux

会提示没有googletest,可以不用理他。

make && make install

受不了太慢

make -j8 && make install

cd install/lib
tree

.
├── libprotobuf.a
├── libprotobuf.la
├── libprotobuf-lite.a
├── libprotobuf-lite.la
├── libprotobuf-lite.so -> libprotobuf-lite.so.28.0.3
├── libprotobuf-lite.so.28 -> libprotobuf-lite.so.28.0.3
├── libprotobuf-lite.so.28.0.3
├── libprotobuf.so -> libprotobuf.so.28.0.3
├── libprotobuf.so.28 -> libprotobuf.so.28.0.3
├── libprotobuf.so.28.0.3
├── libprotoc.a
├── libprotoc.la
├── libprotoc.so -> libprotoc.so.28.0.3
├── libprotoc.so.28 -> libprotoc.so.28.0.3
├── libprotoc.so.28.0.3
└── pkgconfig

├── protobuf-lite.pc
└── protobuf.pc

1 directory, 17 files

file libprotobuf.so.28.0.3 

libprotobuf.so.28.0.3: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (GNU/Linux), dynamically linked, BuildID[sha1]=3dc132b70a58e7012b755b18f076ff625359ef59, with debug_info, not stripped

编译好的头文件与lib文件下载包
protobuf-3.17.3-arm.tar.xz

编译结果

./protoc --version

libprotoc 3.17.3

git clone https://github.com/protocolbuffers/protobuf.git
cd protobuf
git submodule update --init --recursive
mkdir x64
cd x64
../configure --prefix=$(pwd)/install
make
make install

运行编译好的程序

./install/bin/protoc --version

libprotoc 3.17.3
查看所有库文件

tree install/lib/

install/lib/
├── libprotobuf.a
├── libprotobuf.la
├── libprotobuf-lite.a
├── libprotobuf-lite.la
├── libprotobuf-lite.so -> libprotobuf-lite.so.28.0.3
├── libprotobuf-lite.so.28 -> libprotobuf-lite.so.28.0.3
├── libprotobuf-lite.so.28.0.3
├── libprotobuf.so -> libprotobuf.so.28.0.3
├── libprotobuf.so.28 -> libprotobuf.so.28.0.3
├── libprotobuf.so.28.0.3
├── libprotoc.a
├── libprotoc.la
├── libprotoc.so -> libprotoc.so.28.0.3
├── libprotoc.so.28 -> libprotoc.so.28.0.3
├── libprotoc.so.28.0.3
└── pkgconfig

├── protobuf-lite.pc
└── protobuf.pc

编译arm版本protobuf库

cd ../
mkdir arm
cd arm/
CC=arm-linux-gnueabihf-gcc CXX=arm-linux-gnueabihf-g++ ../configure --prefix=$(pwd)/install --host=arm-linux
make -j8
make install
file ./install/bin/protoc 

./install/bin/protoc: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 2.6.32, BuildID[sha1]=cea786b94a0b64b866983c8b4541df34e9cc7c1d, with debug_info, not stripped

protobuf/arm$ tree ./install/lib/

./install/lib/
├── libprotobuf.a
├── libprotobuf.la
├── libprotobuf-lite.a
├── libprotobuf-lite.la
├── libprotobuf-lite.so -> libprotobuf-lite.so.28.0.3
├── libprotobuf-lite.so.28 -> libprotobuf-lite.so.28.0.3
├── libprotobuf-lite.so.28.0.3
├── libprotobuf.so -> libprotobuf.so.28.0.3
├── libprotobuf.so.28 -> libprotobuf.so.28.0.3
├── libprotobuf.so.28.0.3
├── libprotoc.a
├── libprotoc.la
├── libprotoc.so -> libprotoc.so.28.0.3
├── libprotoc.so.28 -> libprotoc.so.28.0.3
├── libprotoc.so.28.0.3
└── pkgconfig

├── protobuf-lite.pc
└── protobuf.pc

使用git 直接git clone github的库,不会报googletest 相关的警告,自动下载好了。如果自己在github.com protobuf release哪儿下载的放在,编译时候会报一个没有googletest的警告。好烦。。

configure: WARNING: no configuration information is in third_party/googletest

Protobuf 的 proto3 与 proto2 的区别
update:2021-8-27
proto3 比 proto2 支持更多语言但 更简洁。去掉了一些复杂的语法和特性,更强调约定而弱化语法。如果是首次使用 Protobuf ,建议使用 proto3 。

在第一行非空白非注释行,必须写:

syntax = "proto3";

  • 字段规则移除了 “required”,并把 “optional” 改名为 “singular”

在 proto2 中 required 也是不推荐使用的。proto3 直接从语法层面上移除了 required 规则。其实可以做的更彻底,把所有字段规则描述都撤销,原来的 repeated 改为在类型或字段名后加一对中括号。这样是不是更简洁?

  • “repeated”字段默认采用 packed 编码;

在 proto2 中,需要明确使用 [packed=true] 来为字段指定比较紧凑的 packed 编码方式。

  • 语言增加 Go、Ruby、JavaNano 支持;
  • 移除了 default 选项;

在 proto2 中,可以使用 default 选项为某一字段指定默认值。在 proto3 中,字段的默认值只能根据字段类型由系统决定。也就是说,默认值全部是约定好的,而不再提供指定默认值的语法。

  • 在字段被设置为默认值的时候,该字段不会被序列化。这样可以节省空间,提高效率。

但这样就无法区分某字段是根本没赋值,还是赋值了默认值。这在 proto3 中问题不大,但在 proto2 中会有问题。

比如,在更新协议的时候使用 default 选项为某个字段指定了一个与原来不同的默认值,旧代码获取到的该字段的值会与新代码不一样。

另一个重约定而弱语法的例子是 Go 语言里的公共/私有对象。Go 语言约定,首字母大写的为公共对象,否则为私有对象。所以在 Go 语言中是没有 public、private 这样的语法的。

  • 枚举类型的第一个字段必须为 0 ;

这也是一个约定。

  • 移除了对分组的支持;

分组的功能完全可以用消息嵌套的方式来实现,并且更清晰。在 proto2 中已经把分组语法标注为『过期』了。这次也算清理垃圾了。

  • 移除了对扩展的支持,新增了 Any 类型;

Any 类型是用来替代 proto2 中的扩展的。目前还在开发中。

proto2 中的扩展特性很像 Swift 语言中的扩展。理解起来有点困难,使用起来更是会带来不少混乱。

相比之下,proto3 中新增的 Any 类型有点像 C/C++ 中的 void* ,好理解,使用起来逻辑也更清晰。

  • 增加了 JSON 映射特性;

语言的活力来自于与时俱进。当前,JSON 的流行有其充分的理由。很多『现代化』的语言都内置了对 JSON 的支持,比如 Go、PHP 等。而 C++ 这种看似保罗万象的学院派语言,因循守旧、故步自封,以致于现出了式微的苗头。
Referenced from:https://blog.csdn.net/huanggang982/article/details/77944174

示例文件main.proto

syntax = "proto3";
package main;

message Test {
    string comment = 1;
}

message Example {
    string name = 1;
    int32 age = 2;
    repeated Test t = 3;

    message Label {
        string source = 1;
    }
    repeated Label labels = 4;
}

示例文件main.txt

name: "Larry"
age: 99
t: [{comment: "hello"}, {comment: "world"}]
labels: [{source: "foo"}, {source: "bar"}]

protoc --encode编码

protoc --encode=main.Example main.proto < main.txt > main.bin

查看main.bin的内容

hexdump -C main.bin 

00000000 0a 05 4c 61 72 72 79 10 63 1a 07 0a 05 68 65 6c |..Larry.c....hel|
00000010 6c 6f 1a 07 0a 05 77 6f 72 6c 64 22 05 0a 03 66 |lo....world"...f|
00000020 6f 6f 22 05 0a 03 62 61 72 |oo"...bar|
00000029

protoc --decode编码

protoc --decode=main.Example main.proto < main.bin 

name: "Larry"
age: 99
t {
comment: "hello"
}
t {
comment: "world"
}
labels {
source: "foo"
}
labels {
source: "bar"
}

示例文件main.proto

syntax = "proto3";
package main;

message Test {
    string comment = 1;
}

message Example {
    string name = 1;
    int32 age = 2;
    repeated Test t = 3;

    message Label {
        string source = 1;
    }
    repeated Label labels = 4;
}

程序代码:

package main
import (
    "fmt"
    "io/ioutil"
    "os"
    "github.com/golang/protobuf/proto"
)

func main() {
    // Open and read the contents of the file
    fp, _ := os.Open("main.txt")
    defer fp.Close()
    data, _ := ioutil.ReadAll(fp)

    // convert the file from type []byte to a string
    text := string(data)

    // initialize the example struct
    ex := Example{}

    // Unmarshal the text into the struct
    _ = proto.UnmarshalText(text, &ex)
    fmt.Println(ex)

    // Create an output file
    fp2, _ := os.Create("gen_main.txt")
    defer fp2.Close()

    // Write the same data back to another file
    _ = proto.MarshalText(fp2, &ex)
}

运行

go run .

{Larry 99 [comment:”hello” comment:”world” ] [source:”foo” source:”bar” ] {} [] 0}