使用Ctypes和Python.h将列表从Python传递到C.

时间:2016-03-18 02:24:42

标签: python c ctypes python-3.5

我正在尝试将空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函数中的值并对其进行修改,它将会修改原始值。

1 个答案:

答案 0 :(得分:3)

您可以将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)调用会(可能)使程序崩溃。