c – 浅拷贝到协议缓冲区的字节字段

假设我有一个具有字节字段的proto:
message MyProto {
    optional bytes data = 1;
}

我不能控制的API给我一个指向源数据及其大小的指针.我想让一个MyProto从这个数据中没有深入的复制.我以为这很容易做,但似乎是不可能的. set_data很容易深入复制. Protobuf提供了一个set_allocated_data函数,但是它需要一个指向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( ??? );
}

有没有办法正确地填充这个proto(这样可以稍后序列化),而不会将源数据深入复制到字节字段中?

我知道我可以立即手动进行序列化,但如果可能的话我宁愿不做.

解决方法

很好的问题选项是:

>如果您可以更改.proto文件,请考虑实施StringPiece的ctype字段选项,Google相当于即将发布的C 17 string_view.这就是Google在内部处理这种情况. FieldOptions消息已经有semantics for StringPiece,但Google还没有开源实施.

message MyProto {
    bytes data = 1 [ctype = STRING_PIECE];
}

有关实施指南,请参见this discussion.您可以忽略竞技场分配的注释,这不适用于您的情况.值得Google询问ETA.
>使用不同的协议缓冲区实现,也许只针对这种特定的消息类型. protobuf-cprotobluff是看起来很有前途的C语言实现.
>向第三方API提供缓冲区.我从评论中看到,你不能,但我把它包括在内.

::str::string* buf = myProto->mutable_data();
buf->reserve(size);
api(buf->data(),size); // data is contiguous per c++11 std

> NON STANDARD:通过覆盖字符串实例中的数据来打破封装. 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
}

注意:这可能会让你被解雇.这对于测试性能影响是有用的,如果你做了零拷贝路由,但不要在prod中.

如果你选择#1,那么如果你可以释放源代码,那么很多人会受益于这个能力.最好的运气.

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...