9

我目前正在尝试在用 C 编写的项目中使用 msgpack。我正在使用 msgpack 来序列化结构的内容,然后将其通过网络发送,并反序列化回相应的结构另一边。

我正在尝试做的精简版:

#include <stdio.h>
#include <msgpack.h>
#include <stdbool.h>

typedef someStruct{
uint32_t a;
uint32_t b;
float    c;
} someStruct;

int main (void){
    someStruct data;
    /* ... Fill 'data' with some data for test purposes ...*/

    msgpack_sbuffer* buff = msgpack_sbuffer_new();
    msgpack_packer* pck = msgpack_packer_new(buff, msgpack_sbuffer_write);        

    someStruct* structs = malloc(sizeof(someStruct) * 10);

    /* ... Fill 'structs' with members containing test data ... */
    // Serialize
    msgpack_pack_array (pck, 10);

    int i;
    for(i = 0 ; i < 10 ; i++){
    msgpack_pack_array (pck, 3);
    msgpack_pack_uint32 (pck, structs[i].a);
    msgpack_pack_uint32 (pck, structs[i].b);
    msgpack_pack_float (pck, structs[i].c);
    }

    free(structs);
    msgpack_packer_free(pck);

    // Deserialize
    msgpack_unpacked msg;
    msgpack_unpacked_init(&msg);
    bool deserialize_success = msgpack_unpack_next
                               (&msg, buff->data, buff->size, NULL);
    if(!deserialize_success) /* Error */

    msgpack_object obj = msg.data;
    msgpack_object_print(stdout,obj); // This seems to work perfectly, indicating serialize / deserialize works as intended...

    someStruct deserialized_data;
    /* Insert code to extract and cast deserialized data to 'deserialized_data */
    // Clean
    msgpack_sbuffer_free(buff);
    msgpack_packer_free(pck);

return 0;
}

列出的代码或多或少直接来自这里,这似乎是 msgpack-c 上为数不多的资源之一。

谁能指出我正确的方向,以“重新创建”电线另一侧的原始结构?我发现实际利用反序列化数据的唯一方法是使用 msgpack_object_print() 调用从 messagepack_object 打印。但是,这确实有效,因此我确定数据在那里。

我是否需要以某种方式遍历序列化数据并使用带有偏移量的 msgpack_unpack_next() 来检索每个 someStruct 成员?使用 memcpy 到本地字节缓冲区?

任何帮助是极大的赞赏!

4

1 回答 1

7

请在下面找到说明如何打包/解包数据的重写版本。

整个想法是以连续的方式打包结构的每个连续字段,并在解包时应用(当然)相同的逻辑。

打包后,您可以随意使用缓冲区(例如通过网络发送、保存在磁盘上等)。

#include <stdio.h>
#include <assert.h>
#include <msgpack.h>

typedef struct some_struct {
  uint32_t a;
  uint32_t b;
  float c;
} some_struct;

static char *pack(const some_struct *s, int num, int *size);
static some_struct *unpack(const void *ptr, int size, int *num);

/* Fixtures */
some_struct ary[] = {
  { 1234, 5678, 3.14f },
  { 4321, 8765, 4.13f },
  { 2143, 6587, 1.34f }
};

int main(void) {
  /** PACK */
  int size;
  char *buf = pack(ary, sizeof(ary)/sizeof(ary[0]), &size);
  printf("pack %zd struct(s): %d byte(s)\n", sizeof(ary)/sizeof(ary[0]), size);

  /** UNPACK */
  int num;
  some_struct *s = unpack(buf, size, &num);
  printf("unpack: %d struct(s)\n", num);

  /** CHECK */
  assert(num == (int) sizeof(ary)/sizeof(ary[0]));
  for (int i = 0; i < num; i++) {
    assert(s[i].a == ary[i].a);
    assert(s[i].b == ary[i].b);
    assert(s[i].c == ary[i].c);
  }
  printf("check ok. Exiting...\n");

  free(buf);
  free(s);

  return 0;
}

static char *pack(const some_struct *s, int num, int *size) {
  assert(num > 0);
  char *buf = NULL;
  msgpack_sbuffer sbuf;
  msgpack_sbuffer_init(&sbuf);
  msgpack_packer pck;
  msgpack_packer_init(&pck, &sbuf, msgpack_sbuffer_write);
  /* The array will store `num` contiguous blocks made of a, b, c attributes */
  msgpack_pack_array(&pck, 3 * num);
  for (int i = 0; i < num; ++i) {
    msgpack_pack_uint32(&pck, s[i].a);
    msgpack_pack_uint32(&pck, s[i].b);
    msgpack_pack_float(&pck, s[i].c);
  }
  *size = sbuf.size;
  buf = malloc(sbuf.size);
  memcpy(buf, sbuf.data, sbuf.size);
  msgpack_sbuffer_destroy(&sbuf);
  return buf;
}

static some_struct *unpack(const void *ptr, int size, int *num) {
  some_struct *s = NULL;
  msgpack_unpacked msg;
  msgpack_unpacked_init(&msg);
  if (msgpack_unpack_next(&msg, ptr, size, NULL)) {
    msgpack_object root = msg.data;
    if (root.type == MSGPACK_OBJECT_ARRAY) {
      assert(root.via.array.size % 3 == 0);
      *num = root.via.array.size / 3;
      s = malloc(root.via.array.size*sizeof(*s));
      for (int i = 0, j = 0; i < root.via.array.size; i += 3, j++) {
        s[j].a = root.via.array.ptr[i].via.u64;
        s[j].b = root.via.array.ptr[i + 1].via.u64;
        s[j].c = root.via.array.ptr[i + 2].via.dec;
      }
    }
  }
  msgpack_unpacked_destroy(&msg);
  return s;
}
于 2013-03-14T09:45:33.613 回答