Как уже упоминалось в другом ответе, вы можете использовать ctypes.py_object
для представления фактического объекта Python, но вы также должны помнить, что при вызове API-интерфейсов Python C нельзя снимать GIL (глобальная блокировка интерпретатора).Для этого используйте PyDLL
вместо CDLL
.
Вот полностью рабочий пример, который работает для последовательностей в целом:
test.c
#include <Python.h>
#ifdef _WIN32
# define API __declspec(dllexport)
#else
define API
#endif
API long sum_list(PyObject* o)
{
Py_ssize_t i, n;
long total = 0, value;
PyObject* list;
PyObject* item;
list = PySequence_Fast(o,"not a sequence"); // New reference! Must DECREF eventually.
if(list == NULL)
return -1;
n = PySequence_Fast_GET_SIZE(list);
for (i = 0; i < PySequence_Fast_GET_SIZE(list); i++) {
item = PySequence_Fast_GET_ITEM(list, i);
if (!PyLong_Check(item))
{
PyErr_SetString(PyExc_TypeError,"sequence contains non-integer");
Py_DECREF(list);
return -1;
}
value = PyLong_AsLong(item);
if (value == -1 && PyErr_Occurred())
{
Py_DECREF(list);
return -1;
}
total += value;
}
Py_DECREF(list);
return total;
}
test.py
from ctypes import *
dll = PyDLL('test')
dll.sum_list.restype = c_long
dll.sum_list.argtypes = py_object,
print(dll.sum_list((1,2,3,4,5)))
try:
print(dll.sum_list(7))
except TypeError as e:
print(e)
try:
print(dll.sum_list((1,2,'a',4,5)))
except TypeError as e:
print(e)
try:
print(dll.sum_list((1,2,0x80000000,4,5)))
except OverflowError as e:
print(e)
try:
print(dll.sum_list((1,2,-0x80000001,4,5)))
except OverflowError as e:
print(e)
Вывод:
15
not a sequence
sequence contains non-integer
Python int too large to convert to C long
Python int too large to convert to C long