gpt4 book ai didi

c - 指针类型与 PyArray_SimpleNew 不匹配

转载 作者:行者123 更新时间:2023-12-04 11:10:09 24 4
gpt4 key购买 nike

我正在使用 C API 为带有 Numpy 的 Python 创建一个模块,遇到了与 PyArray_SimpleNew 输出的奇怪不兼容问题,我想了解这一点。但首先是一个最小的例子:

# include <Python.h>
# include <numpy/arrayobject.h>

void foo()
{
Py_Initialize();
import_array();

npy_intp dims[1] = {42};
PyObject * A = PyArray_SimpleNew(1,dims,NPY_DOUBLE); // Line A

Py_Finalize();
}

int main()
{
foo();
return 0;
}

如果我用 gcc source.c -lpython2.7 -I/usr/include/python2.7 --pedantic 编译它,我得到(引用 A 行):

ISO C forbids conversion of object pointer to function pointer type

因此,显然,出于某种原因,PyArrayObject 应该是函数指针。


根据文档(例如,here),PyArray_SimpleNew 有一个类型为 PyObject * 的返回值,因此上面的代码应该完全没问题。此外,对于返回 PyObject * 的其他函数,我没有收到类似的警告。

现在,虽然这只是我们正在讨论的一个警告,而且我使用 PyArray_SimpleNew 的程序按预期工作,但所有这些都表明 Numpy C API 没有像我认为的那样工作(或已经一个错误)。因此,我想了解这背后的原因。


我在以下系统上生成了以上内容:

  • GCC 4.7.2(Debian 4.7.2-5)、Numpy 1.6.2
  • GCC 4.8.2(Ubuntu 4.8.2-19ubuntu1),Numpy 1.8.2

在这两种情况下,情况都会随着#define NPY_NO_DEPRECATED_API NPY_1_8_API_VERSION而改变。

最佳答案

为了回答您为什么会收到有关“ISO C 禁止将对象指针转换为函数指针类型”的警告的问题,我检查了 numpy 的源代码。

PyArray_SimpleNew 是定义在 numpy/ndarrayobject.h 第 125 行的宏:

#define PyArray_SimpleNew(nd, dims, typenum) \
PyArray_New(&PyArray_Type, nd, dims, typenum, NULL, NULL, 0, 0, NULL)

这会将行 A 扩展为:

PyObject * A = PyArray_New(&PyArray_Type, 1, dims, typenum, NULL, NULL, 0, 0, NULL); // Line A

PyArray_New 本身是在第 1017 行的 numpy/__multiarray_api.h 中定义的宏:

#define PyArray_New \
(*(PyObject * (*)(PyTypeObject *, int, npy_intp *, int, npy_intp *, void *, int, int, PyObject *)) \
PyArray_API[93])

这会将行 A 扩展为:

PyObject * A = (*(PyObject * (*)(PyTypeObject *, int, npy_intp *, int, npy_intp *, void *, int, int, PyObject *))
PyArray_API[93])(&PyArray_Type, 1, dims, typenum, NULL, NULL, 0, 0, NULL); // Line A

这个复杂的表达式可以简化为:

// PyObject * function93(PyTypeObject *, int, npy_intp *, int, npy_intp *, void *, int, int, PyObject *)
typedef PyObject * (*function93)(PyTypeObject *, int, npy_intp *, int, npy_intp *, void *, int, int, PyObject *);

// Get the PyArray API function #93, cast the function pointer to its
// signature, and call it with the arguments to `PyArray_New`.
PyObject * A = (*(function93) PyArray_API[93])(&PyArray_Type, 1, dims, typenum, NULL, NULL, 0, 0, NULL); // Line A

导致禁止转换的部分是:

*(function93) PyArray_API[93]

numpy/__multiarray_api.h 的第 807、810 和 812 行 PyArray_API 是声明为 void **。所以 PyArray_API[93] 是一个 void * (即,一个对象指针)被转换为函数指针。

我对 NumPy 或它的 C-api 不是很熟悉,但看起来你很熟悉正确使用它。 NumPy 恰好使用了一些非标准的、未定义的GCC 支持但 ISO 标准不支持的内部行为(即,NumPy 不符合 ISO 标准)。

另见 [SciPy-User] NumPy C API: where does casting pointer-to-object to pointer-to-function come from?

关于c - 指针类型与 PyArray_SimpleNew 不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28963334/

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