我正在使用C ++ msgpack实现。关于如何打包二进制数据,我遇到了障碍。就二进制数据而言,我有一个以下类型的缓冲区:
unsigned char* data;
数据变量指向一个实际上是图像的数组。我想要做的是使用msgpack打包。似乎没有关于如何实际打包二进制数据的示例。支持format specification原始字节,但我不确定如何使用该功能。
我尝试使用如下字符指针的向量:
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 数组的二进制数据提供建议。
答案 0 :(得分:4)
Josh provided a good answer但它需要将字节缓冲区复制到char矢量。我宁愿最小化复制并直接使用缓冲区(如果可能的话)。以下是另一种解决方案:
查看源代码并尝试根据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的向量)。
答案 1 :(得分:3)
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;
}
免责声明:我通过查看头文件找到了这个,而不是通过阅读序列化原始字节的不存在的文档,所以它可能不是'正确'的方式(虽然它 定义以及序列化程序希望显式处理的所有其他“标准”类型。)
答案 2 :(得分:2)
如果您可以将图片存储在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
),它将无法编译。
答案 3 :(得分:0)
在问题和答案发布后,msgpack-c已更新。 我想告知目前的情况。
由于支持msgpack-c版本2.0.0 C风格的数组。见https://github.com/msgpack/msgpack-c/releases
msgpack -c可以打包const char数组,例如&#34; hello&#34;。 类型转换规则记录在https://github.com/msgpack/msgpack-c/wiki/v2_0_cpp_adaptor#predefined-adaptors。
char数组映射到STR。如果您想使用BIN而不是STR,则需要使用msgpack::type::raw_ref
换行。
这是包装概述。
以下是拆包和转换说明: https://github.com/msgpack/msgpack-c/wiki/v2_0_cpp_object#conversion
解包意味着从MessagePack格式的字节流创建msgpack::object
。转换意味着从msgpack::object
转换为C ++对象。
如果MessagePack格式化数据为STR,隐蔽目标类型为char数组,则将数据复制到数组,如果数组有额外容量,则添加&#39; \ 0&#39;。如果MessagePack格式的数据是BIN,则&#39; \ 0&#39;没有添加。
以下是基于原始问题的代码示例:
#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;
}
}