Cython and Numpy like to access the internals of CPython data structures and make assumptions about the semantics of struct fields.
This is problematic for (at least) two reasons:
We can’t change anything for fear of breaking 3rd party code
We break 3rd party code, despite being careful, because our understanding of the semantics of C structs differs from Cython/Numpy
Therefore, I propose adding a lot of inline static C functions to control access to C structs.
These would be guarded by #ifdef UNSTABLE_ABI.
Initially, most (or all) of these functions won’t have normal API equivalents, in order to avoid making the C-API even larger than it currently is.
We could add the slower stable versions, if there is demand for them.
When we change the internals of PyLongObject again, there would be no need for Cython/Numpy to change their code, although they would need to be recompiled.
We already #include longintrepr.h in Python.h, so all code already has access to the internals.
Adding a new file makes the new functions less discoverable.
TBH I think having different APIs is, in general, a bad idea.
Multiple ABIs, sure. Trading performance for portability.
But there should only be one API, IMO.
Why make these internal APIs (= with underscore) instead of public ones ?
IMO, having a rich Python C API solves most of the “hiding away internals” in the most effective way. If extensions don’t need to go for internal struct fields to have a fast way to determine e.g. whether a Python int is negative, we’d come closer to resolving the issue of putting an abstraction layer between core Python and the huge set of Python extensions, allowing the internals to more forward independently from the extension’s use of the API.
Long term, there is probably no reason not to have these functions as part of the API.
But, for 3.12 at least we want to keep these semi-private until we are sure that we have the API right.