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

How to (de-)serialize PyObject* in C(++)?

我目前正在研究 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,那也很棒! ^_^'

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

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

对于Python和C,选择有点少。有 Google Protocol Buffers here and C version here, Apache Avro here will probably work too, and ASN.1 (if you're feeling brave overview, recommended reference, Playground, Commercial, Commercial,并在 GitHub 上查看一些免费的)。

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

有了可以正常工作的成熟工具,这是一种非常自由的数据交换方式;您可以根据需要在系统中混合使用多种语言。 ASN.1 特别好,因为它的约束系统允许人们非常具体地说明什么是有效数据,什么不是有效数据。强大的接口! Google Protocol Buffers 几乎是完美的(因为它是免费的并且几乎可以做任何事情),但没有任何限制。

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