作者:焦作艾文斯 | 来源:互联网 | 2023-02-05 12:24
假设我有一个带字节字段的proto:
message MyProto {
optional bytes data = 1;
}
我无法控制的API为我提供了指向源数据及其大小的指针.我想在没有深度复制的情况下MyProto
从这些数据中获取数据.我认为这很容易做到,但似乎不可能.深度复制很容易set_data
.Protobuf提供了一个set_allocated_data
函数,但它需要一个指向a的指针std::string
,这对我没有帮助,因为(除非我弄错了)没有办法在std::string
没有深度复制的情况下进行.
void populateProto(void* data, size_t size, MyProto* message) {
// Deep copy is fine, I guess.
message->set_data(data, size);
// Shallow copy would be better...
// message->set_allocated_data( ??? );
}
有没有办法正确填充这个原型(以便以后可以序列化)而无需将源数据深度复制到字节字段中?
我知道我可以立即手动进行序列化,但如果可能的话,我宁愿不这样做.
1> Alejandro C ..:
好问题。选项包括:
如果您可以更改.proto文件,请考虑为实施即将到来的C ++ 17的Google的ctype
field选项。这就是Google在内部处理此类案件的方式。该消息已经具有StringPiece的语义,但是Google尚未开源该实现。StringPiece
string_view
FieldOptions
message MyProto {
bytes data = 1 [ctype = STRING_PIECE];
}
请参阅此讨论以获取实施指南。您可以忽略关于竞技场分配的注释,这不适用于您的情况。值得向Google索取ETA。
使用不同的协议缓冲区实现,可能仅适用于此特定消息类型。protobuf-c和protobluff是看起来很有前途的C语言实现。
向您的第三方API提供缓冲区。我从评论中看到您无法做到,但出于完整性考虑,我将其包括在内。
::str::string* buf = myProto->mutable_data();
buf->resize(size);
api(buf->data(), size); // data is contiguous per c++11 std
非标准:通过覆盖字符串实例中的数据来破坏封装。C ++具有一些粗糙的功能,这些功能可以使您足够绞死自己。此选项不安全,取决于您的std::string
实现和其他因素。
// NEVER USE THIS IN PRODUCTION
void string_jam(::std::string * target, void * buffer, size_t len) {
/* On my system, std::string layout
* 0: size_t capacity
* 8: size_t size
* 16: char * data (iff strlen > 22 chars) */
assert(target->size() > 22);
size_t * size_ptr = (size_t*)target;
size_ptr[0] = len; // Overwrite capacity
size_ptr[1] = len; // Overwrite length
char ** buf_ptr = (char**)(size_ptr + 2);
free(*buf_ptr); // Free the existing buffer
*buf_ptr = (char*)buffer; // Jam in our new buffer
}
注意:这可能会让您被解雇。如果您确实执行了零复制路线,但未在产品中进行,则这对于进行测试以衡量性能影响很有用。
如果使用选项#1,则可以释放源代码就很好了,因为许多其他人将从此功能中受益。祝你好运。