6

我今天开始了我的第一个 Python 扩展,只是在一个 C 库周围创建了一个非常小的包装器作为练习。与 C 库的典型情况一样,您从产生处理程序的初始化函数开始。您可以将该处理程序传递给函数,然后将其传递给释放内存的清理函数。

当我开始编写包装器时,我基本上想有一种方法可以从 python 调用每个本机 C 函数。很快我就遇到了一个问题,我需要从 C 返回一个任意指针到 Python,只是为了在另一个函数中再次将它从那里提供给 C。我不在乎它看起来如何,因为我不在 Python 中使用它,我只是存储它并传递它。

那么如何在 Python 和 C 之间传递一个 void 指针呢?

请注意:我知道不建议使用扩展系统编写如此小的包装器,而是使用 ctypes 和朋友。这只是为了练习。

4

2 回答 2

2

经过一番搜索,我找到了PyLong_AsVoidPtrPyLong_FromVoidPtr函数。void *这产生了一种在 a和 a之间转换的好方法PyObject

# in init function
return PyLong_FromVoidPtr(handle);

# in function using handle
handle = PyLong_AsVoidPtr(python_handle);

现在的一个问题可能是如何python_handle从给定的典型*args函数中检索:

PyObject *python_handle;
PyArg_ParseTuple(args, "O", &python_handle);

这里要小心:为"O"对象提供的参数必须是指向指针的PyObject指针:PyObject **"O"本身仅表示通过它而不PyObject进行任何处理和转换。有了这个,你可以以任何你喜欢的方式传递任何指针。

注意:我认为这个解决方案不是很漂亮,因为你现在必须使用变量,一个只需要很短时间的变量。

于 2013-11-11T01:05:41.083 回答
2

PyLong_FromVoidPtr() 和 PyLong_AsVoidPtr() 可被滥用以将恶意数据注入您的程序。我建议反对他们。

Python 有 PyCapsule 来完成这项工作。Capsules 提供了一种在模块或 Python 空间和 C 空间之间交换 void ptr 的安全方式。胶囊也是类型安全的。如果您需要一些示例,socket / ssl 模块和 pyexpat / _elementtree 模块使用胶囊来交换 CAPI 结构。

http://docs.python.org/3/c-api/capsule.html

于 2013-12-05T21:49:26.063 回答