PEP 757 – C API to import-export Python integers

With this we can introduce new formats with new release. So, why not start simply with digit_array only?

The PyLong_Export would return:

  • -1: error, only possible for non-int’s.
  • 0: success, data is in the digits_array struct. Call PyLong_FreeExport when done.
  • a positive integer, that means some future export format. Callers must call PyLong_FreeExport and then either (1) abort or raise an exception or (2) fall back to PyLong_AsNativeBytes. Later case does make sense if this call will not fail.

with

typedef enum {
    PyLongExport_Error = -1,
    PyLongExport_DigitArray = 0,
} PyLongExport_Kind;
typedef struct PyLongExport {
    Py_uintptr_t _reserved;
    union {
        struct {
            Py_ssize_t ndigits;
            const void *digits;
            uint8_t negative;
        } digits_array;
    } data;  /* I really, really would like to avoid this :( */
} PyLongExport;

gmpy2 code will look closer to the current state, i.e.:

static void
mpz_set_PyLong(mpz_t z, PyObject *obj)
{
    /* here obj is PyLongObject */
    static PyLongExport long_export;
    /* up to user trying first optimizations
       with PyLong_AsLongAndOverflow() */
    PyLongExport_Kind kind = PyLong_Export(obj, &long_export);
    switch (kind) {
    case PyLongExport_DigitArray:
        mpz_import(z, long_export.ndigits, int_digits_order,
                   int_digit_size, int_endianness, int_nails,
                   long_export.digits);
        if (long_export.negative) {
            mpz_neg(z, z);
        }
        PyLong_FreeExport(&long_export);
        break;
    default:
        PyLong_FreeExport(&long_export);
        abort(); /* (1) new release offer new export format */
        /* or (2) fall back to PyLong_AsNativeBytes() */
    }
}

As default case will handle small integers, probably we can bound here requirements for temporary buffer. Then call to PyLong_AsNativeBytes will not fail and option (2) does make sense.

Edit: implemented in PEP 757: edits, based on C-API WG feedback by skirpichev · Pull Request #4026 · python/peps · GitHub