【问题标题】:Pass a list from Python to C with Ctypes and Python.h使用 Ctypes 和 Python.h 将列表从 Python 传递到 C
【发布时间】:2016-03-18 11:43:51
【问题描述】:

我正在尝试将一个空的 result 列表传递给一个 C 函数,该函数可以在 Python 中进行修改和使用。这是我想要做的:

filename = askopenfilename()
result = []
status = self.lib.Cal_readFile(filename, result)

filename 参数很好,但是传递结果变量我得到错误:

status = self.lib.Cal_readFile(filename, result)
ctypes.ArgumentError: argument 2: <class 'TypeError'>: Don't know how to convert parameter 2

我对 ctypes 文档所述的错误并不感到惊讶:

如前所述,除整数之外的所有 Python 类型, 字符串和 unicode 字符串必须包装在它们对应的 ctypes 类型,以便将它们转换为所需的 C 数据 输入

有没有办法解决这个问题?我看不到列表的 ctype。

我本质上想要一个 C 函数在调用时会为我修改的列表。它的工作方式类似于如果我通过引用传递 C 函数中的值并对其进行修改,它将修改原始值。

【问题讨论】:

  • C 没有“列表”类型。您可能必须编写自己的 C 列表库。
  • @franklin 在 C 中我将使用 result 变量作为 PyObject。我在 C 中的包装函数中使用 python.h
  • 您是否同时开发 C 库和加载它的 Python 代码?如果是这样,用 C 编写 Python 模块可能会更容易。在教程中,您还将找到如何传递任何 Python 对象并在 C 代码中操作它们的提示。然后,您还可以编写返回元组的代码,例如 status, result = plugin.read_file(filename) 或抛出异常而不是返回错误代码。
  • @UlrichEckhardt 是的,看起来这就是我想要的。我在这里提出了一个新问题:stackoverflow.com/questions/36091759/…

标签: python c ctypes python-3.5


【解决方案1】:

您可以将ctypes.pydllctypes.py_object 结合使用作为参数类型,以允许传递本机Python 对象。

这是一个最小的例子:

test.c

#include <Python.h>
extern int length(PyObject *obj)
{
    return PyObject_Length(obj);
}

这是使用它的 Python 代码:

>>> lib = ctypes.pydll.LoadLibrary('./test.so')
>>> lib.length.argtypes = [ctypes.py_object]
>>> lib.length([1,2,3])
3
>>> lib.length(None)
Traceback (most recent call last):
  File "<pyshell#85>", line 1, in <module>
    lib.length(None)
TypeError: object of type 'NoneType' has no len()

如果您在 C 代码中使用 Python API,则必须使用 ctypes.pydll 而不是 ctypes.cdll。这可以防止 GIL 被释放,并允许您在 C 代码中安全地调用 Python API 函数。否则,lib.length(None) 调用将(可能)使程序崩溃。

【讨论】:

  • 所以我使用self.lib =CDLL("./Cal.so") 创建了我的库。你是说用PYDLL 代替吗? lib.length.argtypes 行在做什么?我的 C 函数原型如下所示:PyObject *Cal_readFile( PyObject *self, PyObject *args
  • 少打字:lib = ctypes.PyDLL('./test.so')。它还允许您在需要时传递选项,例如 modeuse_errnohandle
  • @Fogest,看起来像在扩展模块中定义的函数(即模块的self 引用;使用PyArg_ParseTuple 解析的args 元组,并返回PyObject *),那么你为什么不创建一个扩展呢?您已经需要编译器,因此 ctypes 的情况很弱。
  • @Fogest 看起来你现在应该创建一个 Python 扩展模块。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-15
  • 2011-03-30
  • 2014-05-02
  • 2021-04-20
  • 2020-08-01
相关资源
最近更新 更多