(These are rough personal notes; don't be fooled by PEP-like wording)
[add some background info here]
Sam's plan was to use dynamic symbol lookup or weak symbols. I propose to not go with a platform-specific solution.
Some of the functions have Python API, e.g. Py_TYPE(o)
is type(o)
in Python. I'm not proposing that: users can redefine type
from Python, breaking type safety.
Instead, I propose we add a capsule,
sys._abi_compat
.
The capsule will contain a bit of version info and the addresses of new
functions.
(Note that users can break this from Python, most easily by del sys._abi_compat
. I'd say a Py_FatalError
is fair in that case, though.
To get wrong behaviour rather than an aborted process, you'd need to create a fake capsule.)
PySys_GetObject
& PyCapsule_GetPointer
. Failure is a fatal error.Since none of these macros are expected to report exceptions,
any failure means Py_FatalError
.
Best way to get/set a PyObject field (assuming the capsule is added), by lowest limited API one needs to support:
ob_refcnt
Py_IncRef
/Py_DecRef
have been functions since before 3.0Py_[X]{INC|DEC|New}REF
) will call Py_IncRef
/Py_DecRef
Py_[X]NewRef
are exported functions; called directlyPy_{INC|DEC|New}REF
) call _Py_IncRef
/_Py_DecRef
insteadPy_CLEAR
and Py_[X]SETREF
remain macros (C-only).
(Add their expansion to the documentation, for benefit of non-C languages.)Py_REFCNT
):
Py_SET_REFCNT
):
ob_type
Py_TYPE
)
Py_SET_TYPE
):
__class__
instead; this includes checks.ob_base
- cast to PyObject*
ob_size
Py_SIZE
)
PyObject_Size
(len(o)
in Python), or specialized functions (PyTuple_Size
). These should be
preferred; how an object uses ob_size
for size information
should generally be treated as its implementation detail.Py_SET_SIZE
)
Existing API:
ob_refcnt
Py_IncRef
/Py_DecRef
Py_NewRef
& Py_XNewRef
Py_INCREF
/Py_DECREF
macros (→ _Py_IncRef
/_Py_DecRef
in 3.10+; Py_IncRef
/Py_DecRef
)Py_XINCREF
/Py_XDECREF
(→ Py_IncRef
/Py_DecRef
)sys.getrefcount(o)
in PythonPy_REFCNT
Py_SetRefcnt
Py_SET_REFCNT
macro (→ _Py_SetRefcnt
)ob_type
type(o)
in PythonPy_TYPE
__class__
ob_base
- cast to PyObject*
ob_size
Py_GetSize
len(o)
Py_SIZE
to call Py_GetSize
, on failure clear the exception & return -1Py_SetSize
Py_GET_SIZE
to call Py_SetSize
, on failure clear the exception