gpt4 book ai didi

c - 将 PyArrayObject 传递给 C 函数

转载 作者:太空宇宙 更新时间:2023-11-03 23:59:17 26 4
gpt4 key购买 nike

我尝试编写一个 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
... */

我想通过对 C 函数的引用来传递 arr。在上面的片段中,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)
^

我(还)不太擅长 C,这可能就是为什么我看不到这里发生了什么。 do_something 接受一个指向结构的指针。因此,在 do something 中取消引用 arr 应该会给我从 test_mod.c 中的 test_mod 函数指向 PyArrayObject 结构的原始指针。这是一种误解吗?如果是,为什么会产生预期的结果?

总结一下,我如何将 PyArrayObject 正确传递给 C 函数,这样就没有警告(关于不兼容的指针类型等)?

最佳答案

再次研究文档后,我发现答案很简单。只需传递结构指针,例如

do_something(arr);

函数本身应为

void do_something(PyArrayObject *arr)
{
int d = PyArray_NDIM(arr));
npy_intp N = PyArray_SIZE(arr);
printf("%i, %li", d, N);
}

此外,在 C 函数没有返回值的情况下,不要忘记增加 Py_None 的引用计数。因此,C 函数的结尾应为

Py_INCREF(Py_None);
return Py_None;

也可以使用内置宏Py_RETURN_NONE,其含义同上两行。

关于c - 将 PyArrayObject 传递给 C 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51188395/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com