[英]msgpack C++ implementation: How to pack binary data?
我正在使用C ++ msgpack实现。 关于如何打包二进制数据,我遇到了障碍。 在二进制数据方面,我有一个以下类型的缓冲区:
unsigned char* data;
数据变量指向一个实际上是图像的数组。 我想要做的是使用msgpack打包。 似乎没有关于如何实际打包二进制数据的示例。 从格式规范支持原始字节,但我不知道如何使用该功能。
我尝试使用如下字符指针的向量:
msgpack::sbuffer temp_sbuffer;
std::vector<char*> vec;
msgpack::pack(temp_sbuffer, vec);
但这会导致编译器错误,因为T = std :: vector没有函数模板。
我还试过以下几点:
msgpack::pack(temp_sbuffer, "Hello");
但这也会导致编译错误(即没有T = const char的函数模板[6]
因此,我希望有人能就如何使用msgpack C ++打包表示为char数组的二进制数据给出建议。
Josh 提供了一个很好的答案,但它需要将字节缓冲区复制到char矢量。 我宁愿最小化复制并直接使用缓冲区(如果可能的话)。 以下是另一种解决方案:
查看源代码并尝试根据我在msgpack::packer<>::pack_raw(size_t l)
和msgpack::packer<>::pack_raw_body(const char* b, size_t l)
msgpack::packer<>::pack_raw(size_t l)
发生的规范确定不同数据类型的打包方式msgpack::packer<>::pack_raw_body(const char* b, size_t l)
。 虽然似乎没有这些方法的文档,但我将如何描述它们。
以下是如何打包字符数组的简单示例:
msgpack::sbuffer temp_sbuffer;
msgpack::packer<msgpack::sbuffer> packer(&temp_sbuffer);
packer.pack_raw(5); // Indicate that you are packing 5 raw bytes
packer.pack_raw_body("Hello", 5); // Pack the 5 bytes
上述示例可以扩展为打包任何二进制数据。 这允许直接从字节数组/缓冲区打包而不必复制到中间数(即char的向量)。
MessagePack有一个raw_ref
类型,您可以这样使用:
#include "msgpack.hpp"
class myClass
{
public:
msgpack::type::raw_ref r;
MSGPACK_DEFINE(r);
};
int _tmain(int argc, _TCHAR* argv[])
{
const char* str = "hello";
myClass c;
c.r.ptr = str;
c.r.size = 6;
// From here on down its just the standard MessagePack example...
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, c);
msgpack::unpacked msg;
msgpack::unpack(&msg, sbuf.data(), sbuf.size());
msgpack::object o = msg.get();
myClass d;
o.convert(&d);
OutputDebugStringA(d.r.ptr);
return 0;
}
免责声明:我,而不是通过阅读连载原始字节不存在的文件发现这周围的头文件戳,所以它可能不会是“正确”的方式(尽管它与所有其他“标准”类型一起定义的serialiser想要显式处理)。
如果您可以将您的图像中的vector<unsigned char>
,而不是原始阵列unsigned char
,那么你就可以收拾该vector
:
#include <iostream>
#include <string>
#include <vector>
#include <msgpack.hpp>
int main()
{
std::vector<unsigned char> data;
for (unsigned i = 0; i < 10; ++i)
data.push_back(i * 2);
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, data);
msgpack::unpacked msg;
msgpack::unpack(&msg, sbuf.data(), sbuf.size());
msgpack::object obj = msg.get();
std::cout << obj << std::endl;
}
奇怪的是,这仅适用于unsigned char
。 如果你试图打包一个char
的缓冲区(甚至是一个单独的char
),它将无法编译。
在问题和答案发布后,msgpack-c已更新。 我想告知目前的情况。
由于支持msgpack-c版本2.0.0 C风格的数组。 请参阅https://github.com/msgpack/msgpack-c/releases
msgpack-c可以打包const char数组,例如“hello”。 类型转换规则记录在https://github.com/msgpack/msgpack-c/wiki/v2_0_cpp_adaptor#predefined-adaptors中 。
char数组映射到STR。 如果要使用BIN而不是STR,则需要使用msgpack::type::raw_ref
进行换msgpack::type::raw_ref
。 这是包装概述。
以下是解压缩和转换说明: https : //github.com/msgpack/msgpack-c/wiki/v2_0_cpp_object#conversion
解包意味着从MessagePack格式的字节流创建msgpack::object
。 转换意味着从msgpack::object
转换为C ++ msgpack::object
。
如果MessagePack格式化数据为STR,隐蔽目标类型为char数组,则将数据复制到数组,如果数组有额外容量,则添加'\\ 0'。 如果MessagePack格式的数据是BIN,则不添加'\\ 0'。
这是基于原始问题的代码示例:
#include <msgpack.hpp>
#include <iostream>
inline
std::ostream& hex_dump(std::ostream& o, char const* p, std::size_t size ) {
o << std::hex << std::setw(2) << std::setfill('0');
while(size--) o << (static_cast<int>(*p++) & 0xff) << ' ';
return o;
}
int main() {
{
msgpack::sbuffer temp_sbuffer;
// since 2.0.0 char[] is supported.
// See https://github.com/msgpack/msgpack-c/wiki/v2_0_cpp_adaptor#predefined-adaptors
msgpack::pack(temp_sbuffer, "hello");
hex_dump(std::cout, temp_sbuffer.data(), temp_sbuffer.size()) << std::endl;
// packed as STR See https://github.com/msgpack/msgpack/blob/master/spec.md
// '\0' is not packed
auto oh = msgpack::unpack(temp_sbuffer.data(), temp_sbuffer.size());
static_assert(sizeof("hello") == 6, "");
char converted[6];
converted[5] = 'x'; // to check overwriting, put NOT '\0'.
// '\0' is automatically added if char-array has enought size and MessagePack format is STR
oh.get().convert(converted);
std::cout << converted << std::endl;
}
{
msgpack::sbuffer temp_sbuffer;
// since 2.0.0 char[] is supported.
// See https://github.com/msgpack/msgpack-c/wiki/v2_0_cpp_adaptor#predefined-adaptors
// packed as BIN
msgpack::pack(temp_sbuffer, msgpack::type::raw_ref("hello", 5));
hex_dump(std::cout, temp_sbuffer.data(), temp_sbuffer.size()) << std::endl;
auto oh = msgpack::unpack(temp_sbuffer.data(), temp_sbuffer.size());
static_assert(sizeof("hello") == 6, "");
char converted[7];
converted[5] = 'x';
converted[6] = '\0';
// only first 5 bytes are written if MessagePack format is BIN
oh.get().convert(converted);
std::cout << converted << std::endl;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.