如何在C(++)中对PyObject *进行(反)序列化?

时间:2018-12-21 18:10:51

标签: python c serialization python-c-api

我目前正在使用C(++)开发多线程python模块。我快完成了,但是我需要做的最后一件事是找到一种围绕GIL的方法,以便线程之间的通信成为可能。

为此,我希望尝试以下伪代码:

// Called from Python
Pyobject* send_data(data, procid) {
    // Change the Python object to byte data and 
    // store it outside of python's memory management.
    serialized = serialize(data);

    // Send the byte data to desired processor
    // (Stored in a queue on that processor)
    send(serialize, procid);
}

// Called from python
Pyobject* receive_data() {
    // Grab data from queue
    serialized = grab_data();

    // De-serialize data
    data = de_serialize(serialized);

    return data;
}

我希望在发送之前序列化数据的原因是由于必须知道已发送数据的内存大小。自sizeof(PyObject*) = 8起,这是我尝试确保尺寸始终正确的方法。

现在,我找到了一种使用pickle在python中序列化数据的方法,但是不知道如何以计算上可接受的方式将其传输到C。 (因此,无需调用启动python实例的函数,即可导入正确的库,并将pickle函数作为可调用的函数发送给C。)

在实现这一目标方面的任何帮助将不胜感激!

当然,如果您知道如何从PyObjects中获取准确的尺寸数据,并且知道如何将其克隆到C中,那也很好! ^ _ ^'

1 个答案:

答案 0 :(得分:1)

当您使用两种不同的语言处理序列化数据时,与语言无关的序列化标准又如何呢?这意味着方案优先方法。

这是避免两次编写每个数据结构定义的最佳方法,一次是用C编写,一次是用Python编写,如果您具有复杂的数据结构,则特别有用。

对于Python和C,选择都比较少。有Google协议缓冲区hereC version here,Apache Avro here可能也可以使用,还有ASN.1(如果您感到勇敢的overviewrecommended referencePlaygroundCommercialCommercial,并在GitHub上查看一些免费的)。

所有这些方法的通用方法是从模式生成Python,C(或C#,Java,C ++)源代码。源代码定义了数据结构,以及将这些数据序列化/反序列化为通用的线格式所需的功能/方法。这些函数的输出/输入是字节数组,因此在C端使用时,它们的内容不会涉及GIL。

有了可以正常工作的成熟工具,这是一种非常自由的数据交换方式;您可以根据需要在系统中混合语言。特别是ASN.1很好,因为它的约束系统允许人们对什么是有效数据非常具体。强大的界面! Google协议缓冲区几乎是完美的(因为它是免费的并且几乎可以执行所有操作),但是没有任何限制。

如果只有简单的数据结构,则两次写入每个结构定义的开销可能不会那么糟。因此,只要它们不只是从Pickle构建Python对象,任何C的体面的Pickle库都可能做得很好。