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

Nathaniel Smith njs@pobox....
Thu Jun 21 10:06:01 CDT 2012


On Thu, Jun 21, 2012 at 2:18 PM, Yury V. Zaytsev <yury@shurup.com> wrote:
> Hi,
>
> I'm trying to get rid of warnings in my C++ code that extensively uses
> NumPy C API. Unfortunately, with gcc 4.6 / -Wall -pedantic, NumPy 1.6.1
> on Fedora Core 16 I get lots of warnings of this kind:
>
>    warning: ISO C++ forbids casting between pointer-to-function and pointer-to-object [enabled by default]
>
> It is generated by this kind of lines:
>
>    PyObject* pObj;
>    ...
>    PyArray_Descr* typecode = PyArray_DescrFromScalar(pObj); // bang!
>    ...
>    int val;
>    PyArray_ScalarAsCtype(pObj, &val); // bang!
>    ...
>    int size = PyArray_Size(pObj); // bang!
>
> ... and so on.
>
> This is highly surprising to me, because the signatures of the functions
> are as follows according to the documentation:
>
>    http://docs.scipy.org/doc/numpy/reference/c-api.array.html
>
>    PyArray_Descr* PyArray_DescrFromScalar(PyObject* scalar)
>    void PyArray_ScalarAsCtype(PyObject* scalar, void* ctypeptr)
>    npy_intp PyArray_Size(PyArrayObject* obj)
>
> I suspect that I can mute these warnings with re-interpret cast gcc
> extension as described here:
>
> http://www.mr-edd.co.uk/blog/supressing_gcc_warnings
>
> but I don't get it what to cast to what and where all this is coming
> from. As it seems to be from the function signatures there shouldn't be
> any problems with type conversion here?!

I suspect that the offending cast here is the one that numpy is doing
internally via a macro. If you look at __multiarray_api.h, you'll see
that when you write PyArray_DescrFromScalar and friends you are not
actually doing a simple function call:

#define PyArray_DescrFromScalar \
        (*(PyArray_Descr * (*)(PyObject *)) \
         PyArray_API[57])

Here PyArray_API is an array of void* which gets populated when you
call import_array(). The reason things work this way are too tiresome
to explain in detail, but it's needed to make dynamic linking play
well with Python dynamic module loading.

Standard C++ apparently does not guarantee that you can cast a void*
to a function pointer:
  http://stackoverflow.com/questions/1096341/function-pointers-casting-in-c
I guess the solution would be to come up with some more elaborate cast
that avoids this warning and works with both C and C++, then teach
numpy/core/code_generators/* to produce it.

-N


More information about the SciPy-User mailing list