与PyArray_SimpleNew的指针类型不匹配 [英] Pointer-type mismatch with PyArray_SimpleNew

查看:103
本文介绍了与PyArray_SimpleNew的指针类型不匹配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用C API为带有Numpy的Python创建一个模块,并且遇到与PyArray_SimpleNew的输出古怪的不兼容,我想了解一下.但首先是一个最小的示例:

I am creating a module for Python with Numpy using the C API and encounter weird incompatibilities with the output of PyArray_SimpleNew, which I would like to understand. But first a minimal example:

# 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行):

If I compile this with gcc source.c -lpython2.7 -I/usr/include/python2.7 --pedantic, I get (with a reference to Line A):

ISO C禁止将对象指针转换为函数指针类型

ISO C forbids conversion of object pointer to function pointer type

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

So, apparently, PyArrayObjects are expected to be function pointers for some reason.

根据文档(例如,

According to the documentation (e.g., here), PyArray_SimpleNew has a return of type PyObject * and thus the above should be perfectly fine. Moreover, I do not get similar warnings with other functions returning PyObject *.

现在,虽然这只是一个警告,我们正在使用PyArray_SimpleNew的程序按预期运行,但所有这些都表明Numpy C API未能按我认为的方式运行(或存在错误).因此,我想了解其背后的原因.

Now, while this is only a warning we are talking about and my programs using PyArray_SimpleNew work as intended, all this indicates that the Numpy C API is not working as I think it is (or has a bug). Therefore I would like to understand the reason behind this.

我是在以下系统上制作的:

I produced the above on the following systems:

  • 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改变.

In neither case, the situation changes with # define NPY_NO_DEPRECATED_API NPY_1_8_API_VERSION.

推荐答案

要回答有关为什么收到"ISO C禁止将对象指针转换为函数指针类型"的警告的问题,我检查了以下代码numpy.

To answer your question about why you're receiving a warning about "ISO C forbids conversion of object pointer to function pointer type", I examined the source code for numpy.

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

PyArray_SimpleNew is a macro defined in numpy/ndarrayobject.h on line 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中定义的宏:

PyArray_New is itself a macro defined in numpy/__multiarray_api.h on line 1017:

#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

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

This complex expression can be simplified to:

// 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

导致禁止转换的部分是:

The part causing the forbidden conversion is:

*(function93) PyArray_API[93]

在807、810和812行的numpy/__multiarray_api.h中的

是 声明为void **.因此PyArray_API[93]void *(即一个对象 指针),将其转换为函数指针.

In numpy/__multiarray_api.h on lines 807, 810, and 812 PyArray_API is declared as void **. So PyArray_API[93] is a void * (i.e., an object pointer) which is being cast as a function pointer.

我对NumPy或其C-api并不真正熟悉,但看起来您像是 正确使用它. NumPy恰好正在使用一些非标准的,未定义的 GCC在内部支持行为,但ISO标准不支持(即NumPy不能被ISO标准移植).

I'm not really familiar with NumPy or its C-api, but it looks like you are using it properly. NumPy just happens to be using some non-standard, undefined behavior internally that GCC supports but the ISO standard does not (i.e., NumPy is not portable by the ISO standard).

另请参见 [SciPy-User] NumPy C API:

这篇关于与PyArray_SimpleNew的指针类型不匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆