python - 通过 ctypes 从 Python 调用 C 代码,使用 python 对象列表
问题描述
我想要
- 用 c写一个
sum_list
sum 一个列表的函数,命名为 sum_list.c - 将
sum_list.c
文件制作为 sum_list.so sum_list = ctypes.CDLL('./sum_list.so')
result = sum_list.sum_list([1, 2, 3])
它在步骤 4 中引发错误:
ctypes.ArgumentError: 参数 1: : 不知道如何转换参数 1
当我在 c 中编写一个添加两个数字的函数时,它可以正常工作。
所以,关键是我不知道如何将列表(python 对象)传递给 c。
sum_list.c
#define PY_SSIZE_T_CLEAN
#include <Python.h>
long sum_list(PyObject *list)
{
Py_ssize_t i, n;
long total = 0, value;
PyObject *item;
n = PyList_Size(list);
if (n < 0)
return -1; /* Not a list */
for (i = 0; i < n; i++) {
item = PyList_GetItem(list, i); /* Can't fail */
if (!PyLong_Check(item)) continue; /* Skip non-integers */
value = PyLong_AsLong(item);
if (value == -1 && PyErr_Occurred())
/* Integer too big to fit in a C long, bail out */
return -1;
total += value;
}
return total;
}
蟒蛇代码
from ctypes import CDLL
sum_list = CDLL('./sum_list.so')
l = [1, 2, 3]
sum_list.sum_list(l)
我希望
var
我的 python 代码中的结果是6
.
解决方案
ctypes 库用于调用纯 C 库中的函数。您找到的示例是用于将进入 Python 扩展模块的函数,并且可以在没有 ctypes 的情况下使用。Ctypes 实际上有一个类型 for PyObject *
,即ctypes.py_object
。您需要将列表包装在其中 - 小心确保它会保持活动状态!
restype
在任何情况下,您几乎总是必须使用and提供正确的函数原型argtypes
。
这是一个工作示例:
import ctypes
sum_list = ctypes.PyDLL('./sum_list.so')
sum_list.restype = ctypes.c_long
sum_list.argtypes = [ ctypes.py_object ]
l = [1, 2, 3]
print(sum_list.sum_list(ctypes.py_object(l)))
请注意,正如 Mark 所指出的,您必须PyDLL
在此处改用,以确保不会释放 GIL,因为该函数没有获取它!
推荐阅读
- delphi - Delphi 10.4 中的研华 DAQNavi ActiveX 组件
- c# - .Where() 中的 .Contains() EF Core 不起作用 .NET Core 3.1.8
- c# - EF Core 2.2 中的 SetDefaultValueSql()
- javascript - NodeJS+request-promise 的并发请求太多
- json - Realm JS react-native无法从具有多对关系的API的大型JSON创建表
- awk - 如何针对 csv 文件循环遍历 txt 文件
- java - 未找到 Java 运行时
- r - 如何解决错误:UseMethod 中的错误(“summarise”)
- python - 关闭浏览器后结束连接 Flask
- firebase - Google Firebase 功能 Firebase auth onCreate 事件处理程序 - 未能配置触发器