Я пытаюсь написать модуль расширения Numpy. Проблема в том, что я не уверен, как правильно передать указатель на PyArrayObject
функции C, что приводит к следующему поведению. Рассмотрим код ниже:
/* File: test_mod.c */
#define NPY_NO_DEPRECATED_API NPY_1_8_API_VERSION
#define PY_ARRAY_UNIQUE_SYMBOL __NP_ARRAY_API
#include <Python.h>
#include <numpy/arrayobject.h>
#include "test_utilities.h"
static PyObject *
test_mod(PyObject* self, PyObject* args) {
PyArrayObject* arr;
if(!PyArg_ParseTuple(args, "O")) {
printf("Error while parsing objects");
return NULL;
}
/* do some checks
... */
do_something(&arr);
return Py_None;
}
/* Method table
... */
/* Module definition structure
... */
/* Module init function
... */
Я хочу передать arr
по ссылке на функцию C. В приведенном выше фрагменте arr
- это указатель на PyArrayObject
, который является C struct
. Поэтому я пришел к следующему определению:
/* File: test_utilities.c */
#define NPY_NO_DEPRECATED_API NPY_1_8_API_VERSION
#define NO_IMPORT_ARRAY
#define PY_ARRAY_UNIQUE_SYMBOL __NP_ARRAY_API
#include <numpy/arrayobject.h>
void
do_something(struct PyArrayObject **arr) {
int d = PyArray_NDIM(*arr));
npy_intp N = PyArray_SIZE(*arr);
printf("%i, %li", d, N);
}
PyArray_NDIM(PyArrayObject* arr)
и PyArray_SIZE(PyArrayObject* arr)
являются макросами из numpy Array API .
После компиляции модуль выдает ожидаемый результат, однако, наряду с некоторыми предупреждениями компилятора. Поэтому я сомневаюсь, что здесь все отлично работает.
Предупреждение для test_modul.c:
test_utilities.h:1:25: warning: declaration of 'struct PyArrayObject'
will not be visible outside of this function [-Wvisibility]
void print_array(struct PyArrayObject **arr);
^
test_modul.c:63:14: warning: incompatible pointer types passing
'PyArrayObject **' (aka 'struct tagPyArrayObject **') to parameter of
type 'struct PyArrayObject **' [-Wincompatible-pointer-types]
do_something(&signal);
^~~~~~~
test_utilities.h:1:41: note: passing argument to parameter 'arr' here
void print_array(struct PyArrayObject **arr);
Предупреждение для test_utilities.c:
test_utilities.c:10:20: warning: declaration of 'struct PyArrayObject'
will not be visible outside of this function [-Wvisibility]
do_something(struct PyArrayObject **arr) {
^
test_utilities.c:13:51: warning: incompatible pointer types passing
'struct PyArrayObject *' to parameter of type 'const PyArrayObject *'
(aka 'const struct tagPyArrayObject *') [-Wincompatible-pointer-types]
printf("Array has: %i dimensions.", PyArray_NDIM(*arr));
^~~~
/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-
packages/numpy/core/include/numpy/ndarraytypes.h:1464:35: note: passing
argument to parameter 'arr' here
PyArray_NDIM(const PyArrayObject *arr)
^
test_utilities.c:16:28: warning: incompatible pointer types passing
'struct PyArrayObject *' to parameter of type 'PyArrayObject *' (aka
'struct tagPyArrayObject *') [-Wincompatible-pointer-types]
npy_intp N = PyArray_SIZE(*arr);
^~~~
/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-
packages/numpy/core/include/numpy/ndarrayobject.h:91:59: note: expanded
from macro 'PyArray_SIZE' #define PyArray_SIZE(m)
PyArray_MultiplyList(PyArray_DIMS(m), PyArray_NDIM(m))
^
/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-
packages/numpy/core/include/numpy/ndarraytypes.h:1482:29: note: passing
argument to parameter 'arr' here
PyArray_DIMS(PyArrayObject *arr)
^
Я (пока) не так хорош в Си, и, вероятно, поэтому я не вижу, что здесь происходит. do_something
принимает указатель на структуру. Следовательно, разыменование arr
в чем-либо должно дать мне исходный указатель на структуру PyArrayObject из функции test_mod
в test_mod.c
. Это неправильное представление, и если да, то почему это дает ожидаемые результаты?
Чтобы подвести итог, как правильно передать PyArrayObject
в функцию C, чтобы не было предупреждений (относительно несовместимых типов указателей и т. Д.)?