Use the limited C API for some of our stdlib C extensions

Well, the limited C API should be… limited. I considered adding PyObject_CallOneArg(), but IMO it’s not worth it: existing PyObject_CallFunctionObjArgs() can be used instead (no major perf difference expected, whereas PyObject_CallNoArgs() has a nice optimization for stack memorty usage).

In the past, we removed functions which were broken or private from the limited C API:

  • 3.11:

    • PyUnicode_CHECK_INTERNED() – was broken
    • PyWeakref_GET_OBJECT() – was broken
    • PyMarshal_WriteLongToFile() – use FILE*
    • PyMarshal_WriteObjectToFile() – use FILE*
    • PyMarshal_ReadObjectFromString() – use FILE*
    • PyMarshal_WriteObjectToString() – use FILE*
  • 3.10:

    • PyOS_ReadlineFunctionPointer() – use FILE*
  • 3.9:

    • PyFPE_START_PROTECT(), PyFPE_END_PROTECT()
    • PyThreadState_DeleteCurrent()
    • _Py_CheckRecursionLimit
    • _Py_NewReference()
    • _Py_ForgetReference()
    • _PyTraceMalloc_NewReference()
    • _Py_GetRefTotal()
    • The trashcan mechanism which never worked in the limited C API.
    • PyTrash_UNWIND_LEVEL
    • Py_TRASHCAN_BEGIN_CONDITION – trashcan never worked in the limited C API
    • Py_TRASHCAN_BEGIN
    • Py_TRASHCAN_END
    • Py_TRASHCAN_SAFE_BEGIN
    • Py_TRASHCAN_SAFE_END

Recently (Python 3.13), I added PyLong_AsInt() to the limited C API. To convert some C extensions to the limited C API, I would like to add the following functions (see PRs attached to the issue):

  • PyMem_RawMalloc()
  • PySys_Audit()
  • PyInterpreterState_IsMain() – new function

History of main Limited C API changes:

  • 3.12: Py_INCREF() and Py_DECREF() are now implemented as opaque function calls (!) in the limited C API version 3.12 and newer (see the discussion).

  • 3.11: for limited C API version 3.11 and newer, <stdlib.h>, <stdio.h>, <errno.h> and <string.h> are no longer included by <Python.h>.

  • 3.10: if Python is built in debug mode (Py_DEBUG), the limited C API is now supported, and Py_INCREF() and Py_DECREF() are implemented as opaque function calls.

  • 3.9:

    • PyObject_INIT() and PyObject_INIT_VAR() are implemented as opaque function calls
    • fix Py_EnterRecursiveCall() and Py_LeaveRecursiveCall() (was broken before), implement them as opaque function calls.
3 Likes