Я работаю над C-расширением для Python, которое реализует метод, который преобразует список numpy элементов (в данном случае numpy.uint64
) в unsigned long long
C-тип (с использованием функции PyLong_AsUnsignedLongLong
). Затем элементы списка суммируются, и полученная сумма возвращается на слой Python.
Чтобы создать модуль, я написал этот код в testmodule.c
:
#include <Python.h>
static PyObject *method_sum_list_u64(PyObject *self, PyObject *args);
static PyMethodDef testmoduleMethods[] = {
{"sum_list_u64", method_sum_list_u64, METH_VARARGS, "docs"},
{NULL, NULL, 0, NULL}
};
static struct PyModuleDef testmodule = {
PyModuleDef_HEAD_INIT,
"testmodule",
"docs",
-1,
testmoduleMethods
};
PyMODINIT_FUNC PyInit_testmodule(void) {
return PyModule_Create(&testmodule);
}
И здесьмой метод:
static PyObject *method_print_list_u64(PyObject *self, PyObject *args) {
uint64_t sum = 0;
PyObject *input_list;
if (!PyArg_ParseTuple(args, "O!", &PyList_Type, &input_list))
{
return NULL;
}
Py_ssize_t data_points = PyList_Size(input_list);
for (Py_ssize_t i = 0; i < data_points; i++)
{
PyObject *item = PyList_GetItem(input_list, i);
sum += PyLong_AsUnsignedLongLong(item);
}
return PyLong_FromUnsignedLongLong(sum);
}
Мой setup.py
файл:
from setuptools import setup, Extension
def main():
setup(name="testmodule",
version="1.0.1",
description="Python interface for the testmodule C library function",
ext_modules=[Extension("testmodule", ["testmodule.c"])])
if __name__ == "__main__":
main()
И простой тестовый скрипт с именем mytest.py
:
import numpy as np
import testmodule
input_list = [np.uint64(1000)]
print(testmodule.sum_list_u64(input_list))
Для воспроизведенияя запускаю ошибку:
$ python setup.py install
$ python mytest.py
TypeError: an integer is required
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "mytest.py", line 5, in <module>
print(testmodule.sum_list_u64(input_list))
SystemError: <built-in function sum_list_u64> returned a result with an error set
Теперь, если я заменю PyLong_AsUnsignedLongLong
на PyLong_AsLongLong
, все работает нормально. Почему PyLong_AsUnsignedLongLong
терпит неудачу, а PyLong_AsLongLong
нет?