C相当于python pickle(对象序列化)?

Bil*_*ill 5 c python client pickle

什么是C等效于这个python代码?谢谢.

data = gather_me_some_data()
# where data = [ (metic, datapoints), ... ]
# and datapoints = [ (timestamp, value), ... ]

serialized_data = cPickle.dumps(data, protocol=-1)
length_prefix = struct.pack("!L", len(serialized_data))
message = length_prefix + serialized_data
Run Code Online (Sandbox Code Playgroud)

Agn*_*kas 7

C不支持直接序列化机制,因为在C中,您无法在运行时获取类型信息.您必须自己在运行时注入一些类型信息,然后通过该类型信息构造所需的对象.因此,定义所有可能的结构:

typedef struct {
  int myInt;
  float myFloat;
  unsigned char myData[MY_DATA_SIZE];
} MyStruct_1;

typedef struct {
  unsigned char myUnsignedChar;
  double myDouble;
} MyStruct_2;
Run Code Online (Sandbox Code Playgroud)

然后定义enum,它收集有关您拥有的结构的信息:

typedef enum {
  ST_MYSTRUCT_1,
  ST_MYSTRUCT_2
} MyStructType;
Run Code Online (Sandbox Code Playgroud)

定义帮助函数,用于确定任何结构大小:

int GetStructSize(MyStructType structType) {
      switch (structType) {
          case ST_MYSTRUCT_1:
              return sizeof(MyStruct_1);
          case ST_MYSTRUCT_2:
              return sizeof(MyStruct_2);
          default:
              // OOPS no such struct in our pocket
              return 0;
      }
}
Run Code Online (Sandbox Code Playgroud)

然后定义序列化函数:

void BinarySerialize(
    MyStructType structType,
    void * structPointer,
    unsigned char * serializedData) {

  int structSize = GetStructSize(structType);

  if (structSize != 0) {
    // copy struct metadata to serialized bytes
    memcpy(serializedData, &structType, sizeof(structType));
    // copy struct itself
    memcpy(serializedData+sizeof(structType), structPointer, structSize);
  }
}
Run Code Online (Sandbox Code Playgroud)

和反序列化功能:

void BinaryDeserialize(
    MyStructType structTypeDestination,
    void ** structPointer,
    unsigned char * serializedData)
{
    // get source struct type
    MyStructType structTypeSource;
    memcpy(&structTypeSource, serializedData, sizeof(structTypeSource));

    // get source struct size
    int structSize = GetStructSize(structTypeSource);

    if (structTypeSource == structTypeDestination && structSize != 0) {
      *structPointer = malloc(structSize);
      memcpy(*structPointer, serializedData+sizeof(structTypeSource), structSize);
    }
}
Run Code Online (Sandbox Code Playgroud)

序列化用法示例:

MyStruct_2 structInput = {0x69, 0.1};
MyStruct_1 * structOutput_1 = NULL;
MyStruct_2 * structOutput_2 = NULL;
unsigned char testSerializedData[SERIALIZED_DATA_MAX_SIZE] = {0};

// serialize structInput
BinarySerialize(ST_MYSTRUCT_2, &structInput, testSerializedData);
// try to de-serialize to something
BinaryDeserialize(ST_MYSTRUCT_1, &structOutput_1, testSerializedData);
BinaryDeserialize(ST_MYSTRUCT_2, &structOutput_2, testSerializedData);
// determine which object was de-serialized
// (plus you will get code-completion support about object members from IDE)
if (structOutput_1 != NULL) {
   // do something with structOutput_1 
   free(structOutput_1);
}
else if (structOutput_2 != NULL) {
   // do something with structOutput_2
   free(structOutput_2);
}
Run Code Online (Sandbox Code Playgroud)

我认为这是C中最简单的序列化方法.但它有一些问题:

  • struct必须没有指针,因为在序列化指针时以及从何处/如何将数据序列化为指针时,您永远不会知道需要分配多少内存.
  • 这个例子有系统endianess的问题 - 你需要注意数据如何存储在内存中 - 以big-endian或little-endian方式和反向字节,如果需要[当转换char *为整合类型时enum](...或重构)代码更便携).


Jan*_*ila 3

如果你会使用C++,有PicklingTools库