Opened 3 months ago

#1182 new defect

python old buffer interface deprecated in python 3

Reported by: pkienzle Owned by:
Priority: minor Milestone: SasView 5.0.0
Component: SasView Keywords:
Cc: Work Package: McSAS Integration Project

Description

The manual claims that the old buffer interface is deprecated in python 3 and some compilers are issuing warnings to that effect.

May want to update to the new buffer interface.

It's going to be a bit of a pain switching. Instead of just grabbing a pointer inside the object, need to create a Py_buffer object at the start of each wrapper and release it at the end. That means if there are any errors, we can't simply return from the function, but instead have to free all the buffers. If we haven't yet allocated all the buffers when we encounter the error, then we need to only free those for which we already allocated.

Here are some really ugly macros that might work:

#define DECLARE_VECTORS(n) \
    Py_buffer VEC_views[n]; \
    int VEC_current = 0;

#define FREE_VECTORS() \
    do { \
        int VEC_k = 0; \
        while (VEC_k < VEC_current) pyBuffer_Release(VEC_views[VEC_k++]); \
     } while (0)

// Could save VEC_max in DECLARE_VECTORS and check that we aren't overflowing VEC_views[]
#define _VECTOR(obj, buf, len, flags) \
    do { \
        Py_buffer *view = VEC_views[VEC_current];
        int err = PyObject_GetBuffer(obj, view, flags); \
        if (err < 0) { FREE_VECTORS(); return NULL; } \
        VEC_current++; \
        if (sizeof(*buf) != view->itemsize) { \
            PyErr_SetString(PyExc_TypeError, "wrong numeric type for vector"); \
            FREE_VECTORS(); \
            return NULL; \
        } \
        buf = view->buf; \
        len = view->len; \
    } while (0)

#define INVECTOR(obj, buf, len) _VECTOR(obj, buf, len, PyBUF_SIMPLE|PyBUF_FORMAT)
#define OUTVECTOR(obj, buf, len) _VECTOR(obj, buf, len, PyBUF_WRITABLE|PyBUF_FORMAT)

Rather than:

    PyObject *in_obj, *out_obj;
    Py_ssize_t nin, nout;
    double *in, *out;
    ...
    INVECTOR(in_obj,in,nin);
    OUTVECTOR(in_obj,in,nin);
    ...
    if (err) {
        PyErr_SetString(...);
        return NULL;
    }
    ...
    return Py_BuildValue(...)

need to do something like:

    PyObject *in_obj, *out_obj;
    Py_ssize_t nin, nout;
    double *in, *out;
    DECLARE_VECTORS(2);
    ...
    INVECTOR(in_obj,in,nin);
    OUTVECTOR(in_obj,in,nin);
    ... 
    if (err) {
        PyErr_SetString(...);
        FREE_VECTORS();
        return NULL;
    }
    ...
    FREE_VECTORS();
    return Py_BuildValue(...)

Change History (0)

Note: See TracTickets for help on using tickets.