On Thu, 2022-07-07 at 22:37 +0000, lpsm...@uw.edu wrote:
> Hello!  I am maintaining a C++ codebase with extensive ties to Python
> bindings (via SWIG).  One of the features of the code is that we
> define (in C) a subclass of a NumPy Array.  Everything worked until
> we started getting this message with numpy 1.23:
> 
>    RuntimeError: Object of type <class 'NamedArray'> appears to be C
> subclassed NumPy array, void scalar, or allocated in a non-standard
> way.NumPy reserves the right to change the size of these structures.
> Projects are required to take this into account by either recompiling
> against a specific NumPy version or padding the struct and enforcing
> a maximum NumPy version.
> 
> My problem is that I don't know how do to either of those things.  I
> would have assumed that whatever I compiled against, it would always
> be compiled against a specific NumPy version, and I also assumed that
> 'enforcing a maximum NumPy version' would happen in requirements.txt
> for the Python package, but that also seems to not be the case.  Any
> hints?  Thank you!


This should only happen if you compile against NumPy 1.19 and then run
your code on NumPy 1.20+.  (The warning is quite a lot older than 1.23
so I am surprised about you mentioning 1.23 specifically.)

Of course you also have to compile with the oldest NumPy version you
wish to support, so that would be a normal thing.

If you don't find the pattern for extending the `PyArrayObject` struct
maybe you can share a bit of the code (we can do that off-list if
necessary).
In principle the warning could be triggered by any bad memory access,
but it seems unlikely...


The normal reason for this (or what the warning tries to inform you
about), is that somewhere in the code you should have the following:

    typedef struct {
        PyArrayObject;
        /* some information you add: */
        char *names;
    } NamedArrayObject;

    PyTypeObject NamedArray_Type = {
        .tp_basicsize = sizeof(NamedArrayObject);
    };
    

A quick hack would be just to add `void *numpy_reserved[2];` after the
`PyArrayObject`, maybe as:

    typedef struct {
        void *reserved[2];
    } numpy_array_padding;

    typedef struct {
        PyArrayObject;
        numpy_array_padding;  /* space for newer NumPy */
        char *names;
    } NamedArrayObject;

Then you can add a runtime check at module initialization:

    sizeof(PyArrayObject) + sizeof(numpy_array+padding)
        >= PyArray_Type.tp_basicsize

To raise an error if a similar incompatibility arises in the future.
(I say `void *reserved[2]` because we appended a single `void *`
twice.)

That padding could be done at run-time as well, but that is a bit
trickier and maybe more hassle than worthwhile.

Hope this helps fixing it quickly!

Cheers,

Sebastian


> 
> -Lucian Smith
> _______________________________________________
> NumPy-Discussion mailing list -- numpy-discussion@python.org
> To unsubscribe send an email to numpy-discussion-le...@python.org
> https://mail.python.org/mailman3/lists/numpy-discussion.python.org/
> Member address: sebast...@sipsolutions.net
> 

Attachment: signature.asc
Description: This is a digitally signed message part

_______________________________________________
NumPy-Discussion mailing list -- numpy-discussion@python.org
To unsubscribe send an email to numpy-discussion-le...@python.org
https://mail.python.org/mailman3/lists/numpy-discussion.python.org/
Member address: arch...@mail-archive.com

Reply via email to