C++ google protobuf
前言
本篇介紹的是TensorRT中用到的幾個與google/protobuf
有關的函數。
google::protobuf
google::protobuf::io::ZeroCopyInputStream
其所屬header檔及命名空間為:
#include <google/protobuf/io/zero_copy_stream_impl.h>
namespace google::protobuf::io
其角色為:
Abstract interface similar to an input stream but
designed to minimize copying.
一個被設計用來減少複製的input stream,為一抽象的interface。
google::protobuf::io::IstreamInputStream
其所屬header檔及命名空間為:
#include <google/protobuf/io/zero_copy_stream_impl.h>
namespace google::protobuf::io
其角色為:
A ZeroCopyInputStream which reads from a C++ istream.
IstreamInputStream
為ZeroCopyInputStream
的子類別,其功能是從C++的istream
中讀取數據。
參考IstreamInputStream constructor,其建構子的簽名為:
explicit IstreamInputStream::IstreamInputStream(
std::istream * stream,
int block_size = -1)
作用為:
Creates a stream that reads from the given C++ istream.
If a block_size is given, it specifies the number of bytes that
should be read and returned with each call to Next().
Otherwise, a reasonable default is used.
即創建一個從C++ istream
裡讀取數據的流。它會讀取block_size
個bytes。
google::protobuf::io::CodedInputStream
其所屬header檔及命名空間為:
#include <google/protobuf/io/coded_stream.h>
namespace google::protobuf::io
其角色為:
Class which reads and decodes binary data which is composed of
varint-encoded integers and fixed-width pieces.
CodedInputStream
用於讀取binary data並對其解碼。
其建構子簽名為:
explicit CodedInputStream(ZeroCopyInputStream * input)
作用為:
Create a CodedInputStream that reads
from the given ZeroCopyInputStream.
可以把CodedInputStream
想成是ZeroCopyInputStream
的wrapper,用於從ZeroCopyInputStream
讀取數據並解碼。
google::protobuf::io::CodedInputStream codedModelStream(&modelStream);## google::protobuf::TextFormat::Parse
SetTotalBytesLimit
參考CodedInputStream::SetTotalBytesLimit,其函數簽名為:
void CodedInputStream::SetTotalBytesLimit(
int total_bytes_limit)
其作用為:
Sets the maximum number of bytes that this CodedInputStream
will read before refusing to continue.
即設定CodedInputStream
物件將讀取的最大bytes數。
PROTOBUF_DEPRECATED_MSG("Please use the single parameter version
of SetTotalBytesLimit(). The " "second parameter is ignored." )
在這個版本中如果給它傳第二個參數將被忽略。
google::protobuf::io::ArrayInputStream
其所屬header檔及命名空間為:
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
namespace google::protobuf::io
其角色為:
A ZeroCopyInputStream backed by an in-memory array of bytes.
ArrayInputStream
為ZeroCopyInputStream
的子類別,用於從記憶體裡的陣列中逐byte地讀取數據。
參考ArrayInputStream - constructor,其建構子簽名為:
ArrayInputStream::ArrayInputStream(
const void * data,
int size,
int block_size = -1)
作用為:
Create an InputStream that returns the bytes pointed to by "data".
即創建一個指向data
這個bytes陣列的InputStream
。
google::protobuf::ShutdownProtobufLibrary
摘自common.h,其所屬header檔及命名空間為:
#include <google/protobuf/stubs/common.h>
namespace google::protobuf
摘自protobuf::ShutdownProtobufLibrary:
Shut down the entire protocol buffers library,
deleting all static-duration objects allocated by
the library or by generated .pb.cc files.
其作用為關閉protobuf library本身。
google::protobuf::TextFormat::Parse
參考google::protobuf::TextFormat::Parse,
其所屬header檔及命名空間為:
#include <google/protobuf/text_format.h>
namespace google::protobuf
其函數簽名為:
static bool TextFormat::Parse(
io::ZeroCopyInputStream * input,
Message * output)
作用為:
Parses a text-format protocol message from the
given input stream to the given message object.
即從給定的ZeroCopyInputStream
裡讀取並解析文字格式的protocol message,存到給定的Message
物件當中。如果成功則回傳true,否則回傳false。
google::protobuf::RepeatedField::Get
repeated_field.h - template class RepeatedField
google::protobuf::RepeatedField
所屬header檔、命名空間及template為:
#include <google/protobuf/repeated_field.h>
namespace google::protobuf
template <typename Element>
其角色為:
RepeatedField is used to represent repeated fields of a primitive type (in other words, everything except strings and nested Messages).
Most users will not ever use a RepeatedField directly; they will use the get-by-index, set-by-index, and add accessors that are generated for all repeated fields.
它是用於表示.proto
檔中的repeated field。
而google::protobuf::RepeatedField::Get
函數的簽名為:
const Element & Get(int index) const
它的作用是獲取repeated field的第index
個元素。
MessageLite::ParseFromCodedStream
參考MessageLite::ParseFromCodedStream:
其所屬header檔及命名空間為:
#include <google/protobuf/message_lite.h>
namespace google::protobuf
它屬於MessageLite
類別的成員函數,其函數簽名為:
bool MessageLite::ParseFromCodedStream(
io::CodedInputStream * input)
其作用為:
Fill the message with a protocol buffer parsed
from the given input stream.
即從給定的input stream裡解析出protocol buffer,並填入message物件中。
參考Protocol Buffer(proto2)及C++ API,此處的MessageLite
有一個名為Message
的子類別。而我們知道.proto
裡的一個message會對應到.proto.pb.h
裡定義的一個類別,而.proto.pb.h
裡定義的每個類別都會實作Message
這個interface。所以每個從.proto
裡來的類別都可以直接調用ParseFromCodedStream
這個函數。
TensorRT中的例子
TensorRT/parsers/caffe/caffeParser/readProto.h
的函數 readBinaryProto
中:
bool readBinaryProto(trtcaffe::NetParameter* net, const char* file, size_t bufSize)
{
//...
using namespace google::protobuf::io;
std::ifstream stream(file, std::ios::in | std::ios::binary);
//...
//創建一個從C++ istream裡讀取數據的流
IstreamInputStream rawInput(&stream);
/*
IstreamInputStream為ZeroCopyInputStream的子類別
從ZeroCopyInputStream讀取數據並解碼。
*/
CodedInputStream codedInput(&rawInput);
//設定CodedInputStream物件將讀取的最大bytes數,第二個參數將被忽略
codedInput.SetTotalBytesLimit(int(bufSize), -1);
/*
從給定的input stream裡解析出protocol buffer,
並填入net這個message物件中
*/
bool ok = net->ParseFromCodedStream(&codedInput);
//...
}
函數readTextProto
:
bool readTextProto(trtcaffe::NetParameter* net, const char* file)
{
//...
using namespace google::protobuf::io;
std::ifstream stream(file, std::ios::in);
//...
IstreamInputStream input(&stream);
/*
從給定的ZeroCopyInputStream裡讀取並解析文字格式的protocol message,
存到給定的Message物件net當中
*/
bool ok = google::protobuf::TextFormat::Parse(&input, net);
//...
}
TensorRT/parsers/caffe/caffeParser/caffeParser.cpp
的函數parse
中:
dims = DimsCHW{(int) mDeploy->input_shape().Get(i).dim().Get(1), (int) mDeploy->input_shape().Get(i).dim().Get(2), (int) mDeploy->input_shape().Get(i).dim().Get(3)};
其中mDeploy->input_shape()
是一個repeated field:
message NetParameter {
//...
repeated BlobShape input_shape = 8;
//...
}
所以mDeploy->input_shape().Get(i)
代表獲取input_shape
的第i
個元素。
我們可以從BlobShape
的定義:
message BlobShape {
repeated int64 dim = 1 [packed = true];
}
中看到,dim
也是一個repeated field。
所以xxx.dim().Get(yyy)
代表獲取dim
的第yyy
個元素。
參考連結
IstreamInputStream constructor
CodedInputStream::SetTotalBytesLimit
ArrayInputStream - constructor
protobuf::ShutdownProtobufLibrary
google::protobuf::TextFormat::Parse
MessageLite::ParseFromCodedStream