PYTHONCAPI\_COMPAT(1) pythoncapi\_compat PYTHONCAPI\_COMPAT(1)

# [NAME](#NAME)

pythoncapi\_compat - pythoncapi\_compat

The **pythoncapi-compat** project can be used to write a C or C++ extension supporting a wide range of Python versions with a single code base. It is made of the **pythoncapi\_compat.h** header file and the **upgrade\_pythoncapi.py** script.

- Homepage: GitHub pythoncapi-compat project &lt;https://github.com/python/pythoncapi-compat&gt;.
- Documentation &lt;https://pythoncapi-compat.readthedocs.io/en/latest/&gt;

Documentation:

# [UPGRADE\_PYTHONCAPI.PY SCRIPT](#UPGRADE_PYTHONCAPI.PY_SCRIPT)

**upgrade\_pythoncapi.py** requires Python 3.6 or newer.

## [Usage](#Usage)

Run the with no arguments to display command line options and list available operations:

```
python3 upgrade_pythoncapi.py
```

## [Select files and directories](#Select_files_and_directories)

To upgrade **module.c** file, type:

```
python3 upgrade_pythoncapi.py module.c
```

To upgrade all C and C++ files (**.c**, **.h**, **.cc**, **.cpp**, **.cxx** and **.hpp** files) in the **directory/** directory, type:

```
python3 upgrade_pythoncapi.py directory/
```

Multiple filenames an directories can be specified on the command line.

Files are modified in-place! If a file is modified, a copy of the original file is created with the **.old** suffix.

## [Select operations](#Select_operations)

To only replace **op-&gt;ob\_type** with **Py\_TYPE(op)**, select the **Py\_TYPE** operation with:

```
python3 upgrade_pythoncapi.py -o Py_TYPE module.c
```

Or the opposite, to apply all operations but leave **op-&gt;ob\_type** unchanged, deselect the **Py\_TYPE** operation with:

```
python3 upgrade_pythoncapi.py -o all,-Py_TYPE module.c
```

## [Download pythoncapi\_compat.h](#Download_pythoncapi_compat.h)

Most **upgrade\_pythoncapi.py** operations add **#include** **"pythoncapi\_compat.h"**. You may have to download the **pythoncapi\_compat.h** header file to your project. It can be downloaded with:

```
python3 upgrade_pythoncapi.py --download PATH
```

## [Upgrade Operations](#Upgrade_Operations)

**upgrade\_pythoncapi.py** implements the following operations:

## [Py\_TYPE](#Py_TYPE)

•

Replace **op-&gt;ob\_type** with **Py\_TYPE(op)**.

## [Py\_SIZE](#Py_SIZE)

•

Replace **op-&gt;ob\_size** with **Py\_SIZE(op)**.

## [Py\_REFCNT](#Py_REFCNT)

•

Replace **op-&gt;ob\_refcnt** with **Py\_REFCNT(op)**.

## [Py\_SET\_TYPE](#Py_SET_TYPE)

- Replace **obj-&gt;ob\_type = type;** with **Py\_SET\_TYPE(obj, type);**.
- Replace **Py\_TYPE(obj) = type;** with **Py\_SET\_TYPE(obj, type);**.

## [Py\_SET\_SIZE](#Py_SET_SIZE)

- Replace **obj-&gt;ob\_size = size;** with **Py\_SET\_SIZE(obj, size);**.
- Replace **Py\_SIZE(obj) = size;** with **Py\_SET\_SIZE(obj, size);**.

## [Py\_SET\_REFCNT](#Py_SET_REFCNT)

- Replace **obj-&gt;ob\_refcnt = refcnt;** with **Py\_SET\_REFCNT(obj, refcnt);**.
- Replace **Py\_REFCNT(obj) = refcnt;** with **Py\_SET\_REFCNT(obj, refcnt);**.

## [Py\_Is](#Py_Is)

- Replace **x == Py\_None** with **Py\_IsNone(x)**.
- Replace **x == Py\_True** with **Py\_IsTrue(x)**.
- Replace **x == Py\_False** with **Py\_IsFalse(x)**.
- Replace **x != Py\_None** with **!Py\_IsNone(x)**.
- Replace **x != Py\_True** with **!Py\_IsTrue(x)**.
- Replace **x != Py\_False** with **!Py\_IsFalse(x)**.

## [PyObject\_NEW](#PyObject_NEW)

- Replace **PyObject\_NEW(...)** with **PyObject\_New(...)**.
- Replace **PyObject\_NEW\_VAR(...)** with **PyObject\_NewVar(...)**.

## [PyMem\_MALLOC](#PyMem_MALLOC)

- Replace [**PyMem\_MALLOC(n)**](/man/enterprise-packages/pythoncapi-compat/PyMem_MALLOC.n) with [**PyMem\_Malloc(n)**](/man/enterprise-packages/pythoncapi-compat/PyMem_Malloc.n).
- Replace **PyMem\_REALLOC(ptr, n)** with **PyMem\_Realloc(ptr, n)**.
- Replace **PyMem\_FREE(ptr)**, **PyMem\_DEL(ptr)** and **PyMem\_Del(ptr)** . with [**PyMem\_Free(n)**](/man/enterprise-packages/pythoncapi-compat/PyMem_Free.n).

## [PyObject\_MALLOC](#PyObject_MALLOC)

- Replace [**PyObject\_MALLOC(n)**](/man/enterprise-packages/pythoncapi-compat/PyObject_MALLOC.n) with [**PyObject\_Malloc(n)**](/man/enterprise-packages/pythoncapi-compat/PyObject_Malloc.n).
- Replace **PyObject\_REALLOC(ptr, n)** with **PyObject\_Realloc(ptr, n)**.
- Replace **PyObject\_FREE(ptr)**, **PyObject\_DEL(ptr)** and **PyObject\_Del(ptr)** . with [**PyObject\_Free(n)**](/man/enterprise-packages/pythoncapi-compat/PyObject_Free.n).

## [PyFrame\_GetBack](#PyFrame_GetBack)

•

Replace **frame-&gt;f\_back** with **\_PyFrame\_GetBackBorrow(frame)**.

## [PyFrame\_GetCode](#PyFrame_GetCode)

•

Replace **frame-&gt;f\_code** with **\_PyFrame\_GetCodeBorrow(frame)**.

## [PyThreadState\_GetInterpreter](#PyThreadState_GetInterpreter)

•

Replace **tstate-&gt;interp** with **PyThreadState\_GetInterpreter(tstate)**.

## [PyThreadState\_GetFrame](#PyThreadState_GetFrame)

•

Replace **tstate-&gt;frame** with **\_PyThreadState\_GetFrameBorrow(tstate)**.

## [Experimental operations](#Experimental_operations)

The following operations are experimental (ex: can introduce compiler warnings) and so not included in the **all** group, they have to be selected explicitly. Example: **-o all,Py\_SETREF**.

Experimental operations:

•

**Py\_NewRef**:

- Replace **Py\_INCREF(res); return res;** with **return Py\_NewRef(res);**
- Replace **x = y; Py\_INCREF(x);** with **x = Py\_NewRef(y);**
- Replace **x = y; Py\_INCREF(y);** with **x = Py\_NewRef(y);**
- Replace **Py\_INCREF(y); x = y;** with **x = Py\_NewRef(y);**

•

**Py\_CLEAR**:

•

Replace **Py\_XDECREF(var); var = NULL;** with **Py\_CLEAR(var);**

•

**Py\_SETREF**:

- Replace **Py\_DECREF(x); x = y;** with **Py\_SETREF(x, y);**
- Replace **Py\_XDECREF(x); x = y;** with **Py\_XSETREF(x, y);**

# [PYTHONCAPI\_COMPAT.H API](#PYTHONCAPI_COMPAT.H_API)

The **pythoncapi\_compat.h** header file provides implementations of recent functions for old Python versions.

Supported Python versions:

- Python 3.6 - 3.15
- PyPy 3.6 - 3.12

C++03 and C++11 are supported on Python 3.6 and newer.

A C11 subset (without optional features) is required, like **static inline** functions: see PEP 7 &lt;https://www.python.org/dev/peps/pep-0007/&gt;.

Some functions related to frame objects and **PyThreadState** are not available on PyPy.

Latest version of the header file: pythoncapi\_compat.h &lt;https://raw.githubusercontent.com/python/pythoncapi-compat/main/pythoncapi\_compat.h&gt;.

## [Python 3.15](#Python_3.15)

[**PyBytesWriter \*PyBytesWriter\_Create(Py\_ssize\_t size)**](#PyBytesWriter)

[**void \*PyBytesWriter\_GetData(PyBytesWriter \*writer)**](#void)

[**Py\_ssize\_t PyBytesWriter\_GetSize(PyBytesWriter \*writer)**](#Py_ssize_t)

**PyObject \*PyBytesWriter\_FinishWithSize(PyBytesWriter \*writer, Py\_ssize\_t size)**

**PyObject \*PyBytesWriter\_Finish(PyBytesWriter \*writer)**

**PyObject \*PyBytesWriter\_FinishWithPointer(PyBytesWriter \*writer, void \*buf)**

[**void PyBytesWriter\_Discard(PyBytesWriter \*writer)**](#void~2)

[**int PyBytesWriter\_Resize(PyBytesWriter \*writer, Py\_ssize\_t size)**](#int)

[**int PyBytesWriter\_Grow(PyBytesWriter \*writer, Py\_ssize\_t size)**](#int~2)

[**void \*PyBytesWriter\_GrowAndUpdatePointer(PyBytesWriter \*writer, Py\_ssize\_t size, void \*buf)**](#void~3)

[**int PyBytesWriter\_WriteBytes(PyBytesWriter \*writer, const void \*bytes, Py\_ssize\_t size)**](#int~3)

[**int PyBytesWriter\_Format(PyBytesWriter \*writer, const char \*format, ...)**](#int~4)

See PyBytesWriter documentation &lt;https://docs.python.org/dev/c-api/bytes.html#pybyteswriter&gt;.

**PyObject \*PySys\_GetAttr(const char \*name)**

See PySys\_GetAttr() documentation &lt;https://docs.python.org/dev/c-api/sys.html#c.PySys\_GetAttr&gt;.

**PyObject \*PySys\_GetAttrString(const char \*name)**

See PySys\_GetAttrString() documentation &lt;https://docs.python.org/dev/c-api/sys.html#c.PySys\_GetAttrString&gt;.

**PyObject \*PySys\_GetOptionalAttr(const char \*name)**

See PySys\_GetOptionalAttr() documentation &lt;https://docs.python.org/dev/c-api/sys.html#c.PySys\_GetOptionalAttr&gt;.

**PyObject \*PySys\_GetOptionalAttrString(const char \*name)**

See PySys\_GetOptionalAttrString() documentation &lt;https://docs.python.org/dev/c-api/sys.html#c.PySys\_GetOptionalAttrString&gt;.

**PyObject \*PyTuple\_FromArray(PyObject \*const \*array, Py\_ssize\_t size)**

See PyTuple\_FromArray() documentation &lt;https://docs.python.org/dev/c-api/tuple.html#c.PyTuple\_FromArray&gt;.

[**Py\_hash\_t PyUnstable\_Unicode\_GET\_CACHED\_HASH(PyObject \*op)**](#Py_hash_t)

See PyUnstable\_Unicode\_GET\_CACHED\_HASH() documentation &lt;https://docs.python.org/dev/c-api/unicode.html#c.PyUnstable\_Unicode\_GET\_CACHED\_HASH&gt;.

On PyPy, always returns **-1**.

[**int PyUnstable\_SetImmortal(PyObject \*op)**](#int~5)

See PyUnstable\_SetImmortal() documentation &lt;https://docs.python.org/dev/c-api/object.html#c.PyUnstable\_SetImmortal&gt;.

Availability: Python 3.13 and newer, not available on PyPy.

## [Python 3.14](#Python_3.14)

[**struct PyLongLayout**](#struct)

See PyLongLayout documentation &lt;https://docs.python.org/dev/c-api/long.html#c.PyLongLayout&gt;.

[**const PyLongLayout &lt;#c.PyLongLayout&gt; \*PyLong\_GetNativeLayout(void)**](#const)

See PyLong\_GetNativeLayout() documentation &lt;https://docs.python.org/dev/c-api/long.html#c.PyLong\_GetNativeLayout&gt;.

[**struct PyLongExport**](#struct~2)

See PyLongExport documentation &lt;https://docs.python.org/dev/c-api/long.html#c.PyLongExport&gt;.

[**int PyLong\_Export(PyObject \*obj, PyLongExport &lt;#c.PyLongExport&gt; \*export\_long)**](#int~6)

See PyLong\_Export() documentation &lt;https://docs.python.org/dev/c-api/long.html#c.PyLong\_Export&gt;.

[**void PyLong\_FreeExport(PyLongExport &lt;#c.PyLongExport&gt; \*export\_long)**](#void~4)

See PyLong\_FreeExport() documentation &lt;https://docs.python.org/dev/c-api/long.html#c.PyLong\_FreeExport&gt;.

[**struct PyLongWriter**](#struct~3)

See PyLongWriter documentation &lt;https://docs.python.org/dev/c-api/long.html#c.PyLongWriter&gt;.

[**PyLongWriter &lt;#c.PyLongWriter&gt; \*PyLongWriter\_Create(int negative, Py\_ssize\_t ndigits, void \*\*digits)**](#PyLongWriter)

See PyLongWriter\_Create() documentation &lt;https://docs.python.org/dev/c-api/long.html#c.PyLongWriter\_Create&gt;.

**PyObject \*PyLongWriter\_Finish(PyLongWriter &lt;#c.PyLongWriter&gt; \*writer)**

See PyLongWriter\_Finish() documentation &lt;https://docs.python.org/dev/c-api/long.html#c.PyLongWriter\_Finish&gt;.

[**void PyLongWriter\_Discard(PyLongWriter &lt;#c.PyLongWriter&gt; \*writer)**](#void~5)

See PyLongWriter\_Discard() documentation &lt;https://docs.python.org/dev/c-api/long.html#c.PyLongWriter\_Discard&gt;.

[**int PyLong\_IsPositive(PyObject \*obj)**](#int~7)

See PyLong\_IsPositive() documentation &lt;https://docs.python.org/dev/c-api/long.html#c.PyLong\_IsPositive&gt;.

[**int PyLong\_IsNegative(PyObject \*obj)**](#int~8)

See PyLong\_IsNegative() documentation &lt;https://docs.python.org/dev/c-api/long.html#c.PyLong\_IsNegative&gt;.

[**int PyLong\_IsZero(PyObject \*obj)**](#int~9)

See PyLong\_IsZero() documentation &lt;https://docs.python.org/dev/c-api/long.html#c.PyLong\_IsZero&gt;.

[**int PyLong\_GetSign(PyObject \*obj, int \*sign)**](#int~10)

See PyLong\_GetSign() documentation &lt;https://docs.python.org/dev/c-api/long.html#c.PyLong\_GetSign&gt;.

**PyObject \*PyIter\_NextItem(PyObject \*sep, PyObject \*iterable)**

See PyIter\_NextItem() documentation &lt;https://docs.python.org/dev/c-api/iter.html#c.PyIter\_NextItem&gt;.

**PyObject \*PyBytes\_Join(PyObject \*sep, PyObject \*iterable)**

See PyBytes\_Join() documentation &lt;https://docs.python.org/dev/c-api/bytes.html#c.PyBytes\_Join&gt;.

[**Py\_hash\_t Py\_HashBuffer(const void \*ptr, Py\_ssize\_t len)**](#Py_hash_t~2)

See Py\_HashBuffer() documentation &lt;https://docs.python.org/dev/c-api/hash.html#c.Py\_HashBuffer&gt;.

[**int PyUnicode\_Equal(PyObject \*str1, PyObject \*str2)**](#int~11)

See PyUnicode\_Equal() documentation &lt;https://docs.python.org/dev/c-api/unicode.html#c.PyUnicode\_Equal&gt;.

[**PyUnicodeWriter \*PyUnicodeWriter\_Create(Py\_ssize\_t length)**](#PyUnicodeWriter)

See PyUnicodeWriter\_Create() documentation &lt;https://docs.python.org/dev/c-api/unicode.html#c.PyUnicodeWriter\_Create&gt;.

**PyObject \*PyUnicodeWriter\_Finish(PyUnicodeWriter \*writer)**

See PyUnicodeWriter\_Finish() documentation &lt;https://docs.python.org/dev/c-api/unicode.html#c.PyUnicodeWriter\_Finish&gt;.

[**void PyUnicodeWriter\_Discard(PyUnicodeWriter \*writer)**](#void~6)

See PyUnicodeWriter\_Discard() documentation &lt;https://docs.python.org/dev/c-api/unicode.html#c.PyUnicodeWriter\_Discard&gt;.

[**int PyUnicodeWriter\_WriteChar(PyUnicodeWriter \*writer, Py\_UCS4 ch)**](#int~12)

See PyUnicodeWriter\_WriteChar() documentation &lt;https://docs.python.org/dev/c-api/unicode.html#c.PyUnicodeWriter\_WriteChar&gt;.

[**int PyUnicodeWriter\_WriteUTF8(PyUnicodeWriter \*writer, const char \*str, Py\_ssize\_t size)**](#int~13)

See PyUnicodeWriter\_WriteUTF8() documentation &lt;https://docs.python.org/dev/c-api/unicode.html#c.PyUnicodeWriter\_WriteUTF8&gt;.

[**int PyUnicodeWriter\_WriteASCII(PyUnicodeWriter \*writer, const char \*str, Py\_ssize\_t size)**](#int~14)

See PyUnicodeWriter\_WriteASCII() documentation &lt;https://docs.python.org/dev/c-api/unicode.html#c.PyUnicodeWriter\_WriteASCII&gt;.

[**int PyUnicodeWriter\_WriteWideChar(PyUnicodeWriter \*writer, const wchar\_t \*str, Py\_ssize\_t size)**](#int~15)

See PyUnicodeWriter\_WriteWideChar() documentation &lt;https://docs.python.org/dev/c-api/unicode.html#c.PyUnicodeWriter\_WriteWideChar&gt;.

[**int PyUnicodeWriter\_WriteStr(PyUnicodeWriter \*writer, PyObject \*obj)**](#int~16)

See PyUnicodeWriter\_WriteStr() documentation &lt;https://docs.python.org/dev/c-api/unicode.html#c.PyUnicodeWriter\_WriteStr&gt;.

[**int PyUnicodeWriter\_WriteRepr(PyUnicodeWriter \*writer, PyObject \*obj)**](#int~17)

See PyUnicodeWriter\_WriteRepr() documentation &lt;https://docs.python.org/dev/c-api/unicode.html#c.PyUnicodeWriter\_WriteRepr&gt;.

[**int PyUnicodeWriter\_WriteSubstring(PyUnicodeWriter \*writer, PyObject \*str, Py\_ssize\_t start, Py\_ssize\_t end)**](#int~18)

See PyUnicodeWriter\_WriteSubstring() documentation &lt;https://docs.python.org/dev/c-api/unicode.html#c.PyUnicodeWriter\_WriteSubstring&gt;.

[**int PyUnicodeWriter\_Format(PyUnicodeWriter \*writer, const char \*format, ...)**](#int~19)

See PyUnicodeWriter\_Format() documentation &lt;https://docs.python.org/dev/c-api/unicode.html#c.PyUnicodeWriter\_Format&gt;.

[**int PyLong\_AsInt32(PyObject \*obj, int32\_t \*pvalue)**](#int~20)

See PyLong\_AsInt32() documentation &lt;https://docs.python.org/dev/c-api/long.html#c.PyLong\_AsInt32&gt;.

[**int PyLong\_AsInt64(PyObject \*obj, int64\_t \*pvalue)**](#int~21)

See PyLong\_AsInt64() documentation &lt;https://docs.python.org/dev/c-api/long.html#c.PyLong\_AsInt64&gt;.

[**int PyLong\_AsUInt32(PyObject \*obj, uint32\_t \*pvalue)**](#int~22)

See PyLong\_AsUInt32() documentation &lt;https://docs.python.org/dev/c-api/long.html#c.PyLong\_AsUInt32&gt;.

[**int PyLong\_AsUInt64(PyObject \*obj, uint64\_t \*pvalue)**](#int~23)

See PyLong\_AsUInt64() documentation &lt;https://docs.python.org/dev/c-api/long.html#c.PyLong\_AsUInt64&gt;.

**PyObject \*PyLong\_FromInt32(int32\_t value)**

See PyLong\_FromInt32() documentation &lt;https://docs.python.org/dev/c-api/long.html#c.PyLong\_FromInt32&gt;.

**PyObject \*PyLong\_FromInt64(int64\_t value)**

See PyLong\_FromInt64() documentation &lt;https://docs.python.org/dev/c-api/long.html#c.PyLong\_FromInt64&gt;.

**PyObject \*PyLong\_FromUInt32(uint32\_t value)**

See PyLong\_FromUInt32() documentation &lt;https://docs.python.org/dev/c-api/long.html#c.PyLong\_FromUInt32&gt;.

**PyObject \*PyLong\_FromUInt64(uint64\_t value)**

See PyLong\_FromUInt64() documentation &lt;https://docs.python.org/dev/c-api/long.html#c.PyLong\_FromUInt64&gt;.

[**FILE \*Py\_fopen(PyObject \*path, const char \*mode)**](#FILE)

See Py\_fopen() documentation &lt;https://docs.python.org/dev/c-api/sys.html#c.Py\_fopen&gt;.

[**int Py\_fclose(FILE \*file)**](#int~24)

See Py\_fclose() documentation &lt;https://docs.python.org/dev/c-api/sys.html#c.Py\_fclose&gt;.

**PyObject \*PyConfig\_Get(const char \*name)**

See PyConfig\_Get() documentation &lt;https://docs.python.org/dev/c-api/init\_config.html#c.PyConfig\_Get&gt;.

[**int PyConfig\_GetInt(const char \*name, int \*value)**](#int~25)

See PyConfig\_GetInt() documentation &lt;https://docs.python.org/dev/c-api/init\_config.html#c.PyConfig\_GetInt&gt;.

[**int PyUnstable\_Object\_IsUniquelyReferenced(PyObject \*op)**](#int~26)

See PyUnstable\_Object\_IsUniquelyReferenced() documentation &lt;https://docs.python.org/dev/c-api/object.html#c.PyUnstable\_Object\_IsUniquelyReferenced&gt;.

Not available on PyPy. **Py\_REFCNT()** semantics is different on PyPy.

[**int PyUnstable\_TryIncRef(PyObject \*op)**](#int~27)

See PyUnstable\_TryIncRef() documentation &lt;https://docs.python.org/dev/c-api/object.html#c.PyUnstable\_TryIncRef&gt;.

Not available on PyPy. **Py\_REFCNT()** semantics is different on PyPy.

[**void PyUnstable\_EnableTryIncRef(PyObject \*op)**](#void~7)

See PyUnstable\_EnableTryIncRef() documentation &lt;https://docs.python.org/dev/c-api/object.html#c.PyUnstable\_EnableTryIncRef&gt;.

Not available on PyPy. **Py\_REFCNT()** semantics is different on PyPy.

Not supported:

- **PyConfig\_Names()**
- **PyConfig\_Set()**
- **PyInitConfig\_AddModule()**
- **PyInitConfig\_Create()**
- **PyInitConfig\_Free()**
- **PyInitConfig\_FreeStrList()**
- **PyInitConfig\_GetError()**
- **PyInitConfig\_GetExitCode()**
- **PyInitConfig\_GetInt()**
- **PyInitConfig\_GetStr()**
- **PyInitConfig\_GetStrList()**
- **PyInitConfig\_HasOption()**
- **PyInitConfig\_SetInt()**
- **PyInitConfig\_SetStr()**
- **PyInitConfig\_SetStrList()**
- **PyType\_GetBaseByToken()**
- **PyUnicodeWriter\_DecodeUTF8Stateful()**
- **PyUnicodeWriter\_WriteUCS4()**
- **Py\_InitializeFromInitConfig()**

## [Python 3.13](#Python_3.13)

[**int PyDict\_GetItemRef(PyObject \*p, PyObject \*key, PyObject \*\*result)**](#int~28)

See PyDict\_GetItemRef() documentation &lt;https://docs.python.org/dev/c-api/dict.html#c.PyDict\_GetItemRef&gt;.

[**int PyDict\_GetItemStringRef(PyObject \*p, const char \*key, PyObject \*\*result)**](#int~29)

See PyDict\_GetItemStringRef() documentation &lt;https://docs.python.org/dev/c-api/dict.html#c.PyDict\_GetItemStringRef&gt;.

**PyObject \*PyImport\_AddModuleRef(const char \*name)**

See PyImport\_AddModuleRef() documentation &lt;https://docs.python.org/dev/c-api/import.html#c.PyImport\_AddModuleRef&gt;.

[**int PyObject\_GetOptionalAttr(PyObject \*obj, PyObject \*attr\_name, PyObject \*\*result)**](#int~30)

See PyObject\_GetOptionalAttr() documentation &lt;https://docs.python.org/dev/c-api/object.html#c.PyObject\_GetOptionalAttr&gt;.

[**int PyObject\_GetOptionalAttrString(PyObject \*obj, const char \*attr\_name, PyObject \*\*result)**](#int~31)

See PyObject\_GetOptionalAttrString() documentation &lt;https://docs.python.org/dev/c-api/object.html#c.PyObject\_GetOptionalAttrString&gt;.

[**int PyObject\_HasAttrWithError(PyObject \*obj, PyObject \*attr\_name)**](#int~32)

See PyObject\_HasAttrWithError() documentation &lt;https://docs.python.org/dev/c-api/object.html#c.PyObject\_HasAttrWithError&gt;.

[**int PyObject\_HasAttrStringWithError(PyObject \*obj, const char \*attr\_name)**](#int~33)

See PyObject\_HasAttrStringWithError() documentation &lt;https://docs.python.org/dev/c-api/object.html#c.PyObject\_HasAttrStringWithError&gt;.

[**int PyMapping\_GetOptionalItem(PyObject \*obj, PyObject \*key, PyObject \*\*result)**](#int~34)

See PyMapping\_GetOptionalItem() documentation &lt;https://docs.python.org/dev/c-api/mapping.html#c.PyMapping\_GetOptionalItem&gt;.

[**int PyMapping\_GetOptionalItemString(PyObject \*obj, const char \*key, PyObject \*\*result)**](#int~35)

See PyMapping\_GetOptionalItemString() documentation &lt;https://docs.python.org/dev/c-api/mapping.html#c.PyMapping\_GetOptionalItemString&gt;.

[**int PyMapping\_HasKeyWithError(PyObject \*obj, PyObject \*key)**](#int~36)

See PyMapping\_HasKeyWithError() documentation &lt;https://docs.python.org/dev/c-api/mapping.html#c.PyMapping\_HasKeyWithError&gt;.

[**int PyMapping\_HasKeyStringWithError(PyObject \*obj, const char \*key)**](#int~37)

See PyMapping\_HasKeyStringWithError() documentation &lt;https://docs.python.org/dev/c-api/mapping.html#c.PyMapping\_HasKeyStringWithError&gt;.

[**int PyModule\_Add(PyObject \*module, const char \*name, PyObject \*value)**](#int~38)

See PyModule\_Add() documentation &lt;https://docs.python.org/dev/c-api/module.html#c.PyModule\_Add&gt;.

[**int PyWeakref\_GetRef(PyObject \*ref, PyObject \*\*pobj)**](#int~39)

See PyWeakref\_GetRef() documentation &lt;https://docs.python.org/dev/c-api/weakref.html#c.PyWeakref\_GetRef&gt;.

[**int Py\_IsFinalizing()**](#int~40)

Return non-zero if the Python interpreter is shutting down, return 0 otherwise.

Availability: Python 3.3 and newer, PyPy 7.3 and newer.

See Py\_IsFinalizing() documentation &lt;https://docs.python.org/dev/c-api/init.html#c.Py\_IsFinalizing&gt;.

[**int PyDict\_ContainsString(PyObject \*p, const char \*key)**](#int~41)

See PyDict\_ContainsString() documentation &lt;https://docs.python.org/dev/c-api/dict.html#c.PyDict\_ContainsString&gt;.

[**int PyLong\_AsInt(PyObject \*obj)**](#int~42)

See PyLong\_AsInt() documentation &lt;https://docs.python.org/dev/c-api/long.html#c.PyLong\_AsInt&gt;.

[**int PyObject\_VisitManagedDict(PyObject \*obj, visitproc visit, void \*arg)**](#int~43)

See PyObject\_VisitManagedDict() documentation &lt;https://docs.python.org/dev/c-api/object.html#c.PyObject\_VisitManagedDict&gt;.

[**void PyObject\_ClearManagedDict(PyObject \*obj)**](#void~8)

See PyObject\_ClearManagedDict() documentation &lt;https://docs.python.org/dev/c-api/object.html#c.PyObject\_ClearManagedDict&gt;.

**PyThreadState \*PyThreadState\_GetUnchecked(void)**

See PyThreadState\_GetUnchecked() documentation &lt;https://docs.python.org/dev/c-api/init.html#c.PyThreadState\_GetUnchecked&gt;.

Available on Python 3.5.2 and newer.

[**int PyUnicode\_EqualToUTF8(PyObject \*unicode, const char \*str)**](#int~44)

See PyUnicode\_EqualToUTF8() documentation &lt;https://docs.python.org/dev/c-api/unicode.html#c.PyUnicode\_EqualToUTF8&gt;.

[**int PyUnicode\_EqualToUTF8AndSize(PyObject \*unicode, const char \*str, Py\_ssize\_t size)**](#int~45)

See PyUnicode\_EqualToUTF8AndSize() documentation &lt;https://docs.python.org/dev/c-api/unicode.html#c.PyUnicode\_EqualToUTF8AndSize&gt;.

[**int PyList\_Extend(PyObject \*list, PyObject \*iterable)**](#int~46)

See PyList\_Extend() documentation &lt;https://docs.python.org/dev/c-api/list.html#c.PyList\_Extend&gt;.

[**int PyList\_Clear(PyObject \*list)**](#int~47)

See PyList\_Clear() documentation &lt;https://docs.python.org/dev/c-api/list.html#c.PyList\_Clear&gt;.

[**int PyDict\_Pop(PyObject \*dict, PyObject \*key, PyObject \*\*result)**](#int~48)

See PyDict\_Pop() documentation &lt;https://docs.python.org/dev/c-api/dict.html#c.PyDict\_Pop&gt;.

[**int PyDict\_PopString(PyObject \*dict, const char \*key, PyObject \*\*result)**](#int~49)

See PyDict\_PopString() documentation &lt;https://docs.python.org/dev/c-api/dict.html#c.PyDict\_PopString&gt;.

[**Py\_hash\_t Py\_HashPointer(const void \*ptr)**](#Py_hash_t~3)

See Py\_HashPointer() documentation &lt;https://docs.python.org/dev/c-api/hash.html#c.Py\_HashPointer&gt;.

[**type PyTime\_t**](#type)

A timestamp or duration in nanoseconds, represented as a signed 64-bit integer.

[**PyTime\_t &lt;#c.PyTime\_t&gt; PyTime\_MIN**](#PyTime_t)

Minimum value of **PyTime\_t**.

[**PyTime\_t &lt;#c.PyTime\_t&gt; PyTime\_MAX**](#PyTime_t~2)

Maximum value of **PyTime\_t**.

[**double PyTime\_AsSecondsDouble(PyTime\_t &lt;#c.PyTime\_t&gt; t)**](#double)

See PyTime\_AsSecondsDouble() documentation &lt;https://docs.python.org/dev/c-api/time.html#c.PyTime\_AsSecondsDouble&gt;.

[**int PyTime\_Monotonic(PyTime\_t &lt;#c.PyTime\_t&gt; \*result)**](#int~50)

See PyTime\_Monotonic() documentation &lt;https://docs.python.org/dev/c-api/time.html#c.PyTime\_Monotonic&gt;.

[**int PyTime\_Time(PyTime\_t &lt;#c.PyTime\_t&gt; \*result)**](#int~51)

See PyTime\_Time() documentation &lt;https://docs.python.org/dev/c-api/time.html#c.PyTime\_Time&gt;.

[**int PyTime\_PerfCounter(PyTime\_t &lt;#c.PyTime\_t&gt; \*result)**](#int~52)

See PyTime\_PerfCounter() documentation &lt;https://docs.python.org/dev/c-api/time.html#c.PyTime\_PerfCounter&gt;.

**PyObject \*PyList\_GetItemRef(PyObject \*op, Py\_ssize\_t index)**

See PyList\_GetItemRef() documentation &lt;https://docs.python.org/dev/c-api/list.html#c.PyList\_GetItemRef&gt;.

[**int PyDict\_SetDefaultRef(PyObject \*d, PyObject \*key, PyObject \*default\_value, PyObject \*\*result)**](#int~53)

See PyDict\_SetDefaultRef() documentation &lt;https://docs.python.org/dev/c-api/dict.html#c.PyDict\_SetDefaultRef&gt;.

Not supported:

- **PyErr\_FormatUnraisable()**.
- **PyLong\_AsNativeBytes()**
- **PyLong\_FromNativeBytes()**
- **PyLong\_FromUnsignedNativeBytes()**
- **PyObject\_GenericHash()**.
- **PySys\_Audit()**.
- **PySys\_AuditTuple()**.
- **PyType\_GetFullyQualifiedName()**
- **PyType\_GetModuleName()**

## [Python 3.12](#Python_3.12)

**PyObject \*PyFrame\_GetVar(PyFrameObject \*frame, PyObject \*name)**

See PyFrame\_GetVar() documentation &lt;https://docs.python.org/dev/c-api/frame.html#c.PyFrame\_GetVar&gt;.

Not available on PyPy.

**PyObject \*PyFrame\_GetVarString(PyFrameObject \*frame, const char \*name)**

See PyFrame\_GetVarString() documentation &lt;https://docs.python.org/dev/c-api/frame.html#c.PyFrame\_GetVarString&gt;.

Not available on PyPy.

**PyObject \*Py\_GetConstant(unsigned int constant\_id)**

See Py\_GetConstant() documentation &lt;https://docs.python.org/dev/c-api/object.html#c.Py\_GetConstant&gt;.

**PyObject \*Py\_GetConstantBorrowed(unsigned int constant\_id)**

See Py\_GetConstantBorrowed() documentation &lt;https://docs.python.org/dev/c-api/object.html#c.Py\_GetConstantBorrowed&gt;.

Not supported:

- **PyDict\_AddWatcher()**, **PyDict\_Watch()**.
- **PyCode\_AddWatcher()**, **PyCode\_ClearWatcher()**.
- **PyErr\_GetRaisedException()**, **PyErr\_SetRaisedException()**.
- **\_PyErr\_ChainExceptions1()**.
- **PyErr\_DisplayException()**.
- **\_Py\_IsImmortal()**.
- **Py\_NewInterpreterFromConfig()**.
- **PyException\_GetArgs()**, **PyException\_SetArgs()**.
- **PyEval\_SetProfileAllThreads()**, **PyEval\_SetTraceAllThreads()**.
- **PyFunction\_SetVectorcall()**.
- **PyType\_FromMetaclass()**: implementation too big to be backported.
- **PyVectorcall\_Call()**.

## [Python 3.11](#Python_3.11)

**PyObject \*PyCode\_GetCellvars(PyCodeObject \*code)**

See PyCode\_GetCellvars() documentation &lt;https://docs.python.org/dev/c-api/code.html#c.PyCode\_GetCellvars&gt;.

Not available on PyPy.

**PyObject \*PyCode\_GetCode(PyCodeObject \*code)**

See PyCode\_GetCode() documentation &lt;https://docs.python.org/dev/c-api/code.html#c.PyCode\_GetCode&gt;.

Not available on PyPy.

**PyObject \*PyCode\_GetFreevars(PyCodeObject \*code)**

See PyCode\_GetFreevars() documentation &lt;https://docs.python.org/dev/c-api/code.html#c.PyCode\_GetFreevars&gt;.

Not available on PyPy.

**PyObject \*PyCode\_GetVarnames(PyCodeObject \*code)**

See PyCode\_GetVarnames() documentation &lt;https://docs.python.org/dev/c-api/code.html#c.PyCode\_GetVarnames&gt;.

Not available on PyPy.

**PyObject \*PyFrame\_GetBuiltins(PyFrameObject \*frame)**

See PyFrame\_GetBuiltins() documentation &lt;https://docs.python.org/dev/c-api/frame.html#c.PyFrame\_GetBuiltins&gt;.

Not available on PyPy.

**PyObject \*PyFrame\_GetGlobals(PyFrameObject \*frame)**

See PyFrame\_GetGlobals() documentation &lt;https://docs.python.org/dev/c-api/frame.html#c.PyFrame\_GetGlobals&gt;.

Not available on PyPy.

[**int PyFrame\_GetLasti(PyFrameObject \*frame)**](#int~54)

See PyFrame\_GetLasti() documentation &lt;https://docs.python.org/dev/c-api/frame.html#c.PyFrame\_GetLasti&gt;.

Not available on PyPy.

**PyObject \*PyFrame\_GetLocals(PyFrameObject \*frame)**

See PyFrame\_GetLocals() documentation &lt;https://docs.python.org/dev/c-api/frame.html#c.PyFrame\_GetLocals&gt;.

Not available on PyPy.

[**void PyThreadState\_EnterTracing(PyThreadState \*tstate)**](#void~9)

See PyThreadState\_EnterTracing() documentation &lt;https://docs.python.org/dev/c-api/init.html#c.PyThreadState\_EnterTracing&gt;.

Not available on PyPy.

[**void PyThreadState\_LeaveTracing(PyThreadState \*tstate)**](#void~10)

See PyThreadState\_LeaveTracing() documentation &lt;https://docs.python.org/dev/c-api/init.html#c.PyThreadState\_LeaveTracing&gt;.

Not available on PyPy

[**int PyFloat\_Pack2(double x, unsigned char \*p, int le)**](#int~55)

Pack a C double as the IEEE 754 binary16 half-precision format.

Availability: Python 3.6 and newer. Not available on PyPy

[**int PyFloat\_Pack4(double x, unsigned char \*p, int le)**](#int~56)

Pack a C double as the IEEE 754 binary32 single precision format.

Not available on PyPy

[**int PyFloat\_Pack8(double x, unsigned char \*p, int le)**](#int~57)

Pack a C double as the IEEE 754 binary64 double precision format.

Not available on PyPy

[**double PyFloat\_Unpack2(const unsigned char \*p, int le)**](#double~2)

Unpack the IEEE 754 binary16 half-precision format as a C double.

Availability: Python 3.6 and newer. Not available on PyPy

[**double PyFloat\_Unpack4(const unsigned char \*p, int le)**](#double~3)

Unpack the IEEE 754 binary32 single precision format as a C double.

Not available on PyPy

[**double PyFloat\_Unpack8(const unsigned char \*p, int le)**](#double~4)

Unpack the IEEE 754 binary64 double precision format as a C double.

Not available on PyPy

Not supported:

- **PyType\_GetModuleByDef()**.
- **PyType\_GetName()**.
- **PyType\_GetQualName()**.
- **Py\_Version** constant.
- **PyErr\_GetHandledException()**, **PyErr\_SetHandledException()**.
- **PyFrame\_GetGenerator()**.

## [Python 3.10](#Python_3.10)

**PyObject \*Py\_NewRef(PyObject \*obj)**

See Py\_NewRef() documentation &lt;https://docs.python.org/dev/c-api/refcounting.html#c.Py\_NewRef&gt;.

**PyObject \*Py\_XNewRef(PyObject \*obj)**

See Py\_XNewRef() documentation &lt;https://docs.python.org/dev/c-api/refcounting.html#c.Py\_XNewRef&gt;.

[**int Py\_Is(PyObject \*x, PyObject \*y)**](#int~58)

See Py\_Is() documentation &lt;https://docs.python.org/dev/c-api/structures.html#c.Py\_Is&gt;.

[**int Py\_IsNone(PyObject \*x)**](#int~59)

See Py\_IsNone() documentation &lt;https://docs.python.org/dev/c-api/structures.html#c.Py\_IsNone&gt;.

[**int Py\_IsTrue(PyObject \*x)**](#int~60)

See Py\_IsTrue() documentation &lt;https://docs.python.org/dev/c-api/structures.html#c.Py\_IsTrue&gt;.

[**int Py\_IsFalse(PyObject \*x)**](#int~61)

See Py\_IsFalse() documentation &lt;https://docs.python.org/dev/c-api/structures.html#c.Py\_IsFalse&gt;.

[**int PyModule\_AddObjectRef(PyObject \*module, const char \*name, PyObject \*value)**](#int~62)

See PyModule\_AddObjectRef() documentation &lt;https://docs.python.org/dev/c-api/module.html#c.PyModule\_AddObjectRef&gt;.

Not supported:

- **PyCodec\_Unregister()**.
- **PyDateTime\_DATE\_GET\_TZINFO()**, **PyDateTime\_TIME\_GET\_TZINFO()**.
- **PyErr\_SetInterruptEx()**.
- **PyGC\_Enable()**, **PyGC\_Disable()** and **PyGC\_IsEnabled()**.
- **PyIter\_Send()**.
- **PySet\_CheckExact()**.
- **Py\_TPFLAGS\_DISALLOW\_INSTANTIATION** constant.
- **Py\_TPFLAGS\_IMMUTABLETYPE** constant.

## [Python 3.9](#Python_3.9)

## [PyObject](#PyObject)

[**void Py\_SET\_REFCNT(PyObject \*ob, Py\_ssize\_t refcnt)**](#void~11)

See Py\_SET\_REFCNT() documentation &lt;https://docs.python.org/dev/c-api/structures.html#c.Py\_SET\_REFCNT&gt;.

[**void Py\_SET\_TYPE(PyObject \*ob, PyTypeObject \*type)**](#void~12)

See Py\_SET\_TYPE() documentation &lt;https://docs.python.org/dev/c-api/structures.html#c.Py\_SET\_TYPE&gt;.

[**void Py\_SET\_SIZE(PyVarObject \*ob, Py\_ssize\_t size)**](#void~13)

See Py\_SET\_SIZE() documentation &lt;https://docs.python.org/dev/c-api/structures.html#c.Py\_SET\_SIZE&gt;.

[**int Py\_IS\_TYPE(const PyObject \*ob, const PyTypeObject \*type)**](#int~63)

See Py\_IS\_TYPE() documentation &lt;https://docs.python.org/dev/c-api/structures.html#c.Py\_IS\_TYPE&gt;.

**PyObject \*PyObject\_CallNoArgs(PyObject \*func)**

See PyObject\_CallNoArgs() documentation &lt;https://docs.python.org/dev/c-api/call.html#c.PyObject\_CallNoArgs&gt;.

**PyObject \*PyObject\_CallOneArg(PyObject \*func, PyObject \*arg)**

See PyObject\_CallOneArg() documentation &lt;https://docs.python.org/dev/c-api/call.html#c.PyObject\_CallOneArg&gt;.

**PyObject \*PyObject\_Vectorcall(PyObject \*callable, PyObject \*const \*args, size\_t nargsf, PyObject \*kwnames)**

See PyObject\_Vectorcall() documentation &lt;https://docs.python.org/dev/c-api/call.html#c.PyObject\_Vectorcall&gt;.

[**Py\_ssize\_t PyVectorcall\_NARGS(size\_t nargsf)**](#Py_ssize_t~2)

See PyVectorcall\_NARGS() documentation &lt;https://docs.python.org/dev/c-api/call.html#c.PyVectorcall\_NARGS&gt;.

[**PY\_VECTORCALL\_ARGUMENTS\_OFFSET**](#PY_VECTORCALL_ARGUMENTS_OFFSET)

See PY\_VECTORCALL\_ARGUMENTS\_OFFSET documentation &lt;https://docs.python.org/dev/c-api/call.html#PY\_VECTORCALL\_ARGUMENTS\_OFFSET&gt;.

Not supported:

- **PyVectorcall\_CallMethod()**.
- **PyType\_FromModuleAndSpec()**

## [PyFrameObject](#PyFrameObject)

[**PyCodeObject \*PyFrame\_GetCode(PyFrameObject \*frame)**](#PyCodeObject)

See PyFrame\_GetCode() documentation &lt;https://docs.python.org/dev/c-api/reflection.html#c.PyFrame\_GetCode&gt;.

**PyFrameObject \*PyFrame\_GetBack(PyFrameObject \*frame)**

See PyFrame\_GetBack() documentation &lt;https://docs.python.org/dev/c-api/reflection.html#c.PyFrame\_GetBack&gt;.

Not available on PyPy

## [PyThreadState](#PyThreadState)

**PyFrameObject \*PyThreadState\_GetFrame(PyThreadState \*tstate)**

See PyThreadState\_GetFrame() documentation &lt;https://docs.python.org/dev/c-api/init.html#c.PyThreadState\_GetFrame&gt;.

Not available on PyPy

**PyInterpreterState \*PyThreadState\_GetInterpreter(PyThreadState \*tstate)**

See PyThreadState\_GetInterpreter() documentation &lt;https://docs.python.org/dev/c-api/init.html#c.PyThreadState\_GetInterpreter&gt;.

[**uint64\_t PyThreadState\_GetID(PyThreadState \*tstate)**](#uint64_t)

See PyThreadState\_GetID() documentation &lt;https://docs.python.org/dev/c-api/init.html#c.PyThreadState\_GetID&gt;.

Availability: Python 3.7. Not available on PyPy.

## [PyInterpreterState](#PyInterpreterState)

**PyInterpreterState \*PyInterpreterState\_Get(void)**

See PyInterpreterState\_Get() documentation &lt;https://docs.python.org/dev/c-api/init.html#c.PyInterpreterState\_Get&gt;.

## [GC protocol](#GC_protocol)

[**int PyObject\_GC\_IsTracked(PyObject \*obj)**](#int~64)

See PyObject\_GC\_IsTracked() documentation &lt;https://docs.python.org/dev/c-api/gcsupport.html#c.PyObject\_GC\_IsTracked&gt;.

Not available on PyPy.

[**int PyObject\_GC\_IsFinalized(PyObject \*obj)**](#int~65)

See PyObject\_GC\_IsFinalized() documentation &lt;https://docs.python.org/dev/c-api/gcsupport.html#c.PyObject\_GC\_IsFinalized&gt;.

Availability: Python 3.4. Not available on PyPy.

## [Module helper](#Module_helper)

[**int PyModule\_AddType(PyObject \*module, PyTypeObject \*type)**](#int~66)

See PyModule\_AddType() documentation &lt;https://docs.python.org/dev/c-api/module.html#c.PyModule\_AddType&gt;.

## [Python 3.8](#Python_3.8)

Not supported:

•

**PyCode\_NewWithPosOnlyArgs()**.

## [Python 3.7](#Python_3.7)

Not supported:

- **PyImport\_GetModule()**.
- **PyInterpreterState\_GetID()**.
- **PySlice\_Unpack()**, **PySlice\_AdjustIndices()**.
- **PyTimeZone\_FromOffset()**, **PyTimeZone\_FromOffsetAndName()**.
- **Py\_RETURN\_RICHCOMPARE()**.
- **Py\_UNREACHABLE** macro.

## [Python 3.6](#Python_3.6)

Not supported:

- **PyErr\_ResourceWarning()**.
- **PyErr\_SetImportErrorSubclass()**.
- **PyOS\_FSPath()**.
- **Py\_FinalizeEx()**.

## [Python 3.5.2](#Python_3.5.2)

[**Py\_SETREF(op, op2)**](#Py_SETREF%28op,)

[**Py\_XSETREF(op, op2)**](#Py_XSETREF%28op,)

Not supported:

- **PyCodec\_NameReplaceErrors()**.
- **PyErr\_FormatV()**.
- **PyExc\_RecursionError**.
- **PyModule\_FromDefAndSpec()**, **PyModule\_FromDefAndSpec2()**, and **PyModule\_ExecDef()**.
- **PyNumber\_MatrixMultiply()** and **PyNumber\_InPlaceMatrixMultiply()**.

## [Python 3.4](#Python_3.4)

[**Py\_UNUSED(name)**](#Py_UNUSED%28name%29)

See Py\_UNUSED() documentation &lt;https://docs.python.org/dev/c-api/intro.html#c.Py\_UNUSED&gt;.

## [Python 3.2](#Python_3.2)

Not supported:

- **Py\_VA\_COPY**.
- **PySys\_SetArgvEx()**.
- **PyLong\_AsLongLongAndOverflow()**.
- **PyErr\_NewExceptionWithDoc()**.

## [Python 3.1](#Python_3.1)

Not supported:

- **PyOS\_string\_to\_double()**.
- **PyCapsule** API.

## [Borrow variant](#Borrow_variant)

To ease migration of C extensions to the new C API, a variant is provided to return borrowed references rather than strong references.

These functions are only available in **pythoncapi\_compat.h** and are not part of the Python C API.

**PyObject \*\_Py\_StealRef(PyObject \*ob)**

Similar to **Py\_DECREF(ob); return ob;**.

**PyObject \*\_Py\_XStealRef(PyObject \*ob)**

Similar to **Py\_XDECREF(ob); return ob;**.

**PyFrameObject \*\_PyThreadState\_GetFrameBorrow(PyThreadState \*tstate)**

**PyThreadState\_GetFrame()** variant. Not available on PyPy.

[**PyCodeObject \*\_PyFrame\_GetCodeBorrow(PyFrameObject \*frame)**](#PyCodeObject~2)

**PyFrame\_GetCode()** variant.

**PyFrameObject \*\_PyFrame\_GetBackBorrow(PyFrameObject \*frame)**

**PyFrame\_GetBack()** variant Not available on PyPy.

For example, **tstate-&gt;frame** can be replaced with **\_PyThreadState\_GetFrameBorrow(tstate)** to avoid accessing directly **PyThreadState.frame** member.

# [PYTHONCAPI-COMPAT USERS](#PYTHONCAPI-COMPAT_USERS)

## [Examples of projects using pythoncapi\_compat.h](#Examples_of_projects_using_pythoncapi_compat.h)

- bitarray &lt;https://github.com/ilanschnell/bitarray/&gt;: **bitarray/\_bitarray.c** uses **Py\_SET\_SIZE()** (pythoncapi\_compat.h copy &lt;https://github.com/ilanschnell/bitarray/blob/master/bitarray/pythoncapi\_compat.h&gt;)
- datatable &lt;https://github.com/h2oai/datatable&gt; (commit &lt;https://github.com/h2oai/datatable/commit/02f13114828ed4567e4410f5bac579895e20355a&gt;)
- guppy3 &lt;https://github.com/zhuyifei1999/guppy3/&gt; (commit &lt;https://github.com/zhuyifei1999/guppy3/commit/4cb9fcb5d75327544a6875b6caabfdffb70a7e29&gt;)
- immutables &lt;https://github.com/MagicStack/immutables/&gt;: **immutables/\_map.c** uses **Py\_SET\_SIZE()** (pythoncapi\_compat.h copy &lt;https://github.com/MagicStack/immutables/blob/master/immutables/pythoncapi\_compat.h&gt;)
- Mercurial (hg) &lt;https://www.mercurial-scm.org/&gt; uses **Py\_SET\_TYPE()** (commit &lt;https://www.mercurial-scm.org/repo/hg/rev/e92ca942ddca&gt;, pythoncapi\_compat.h copy &lt;https://www.mercurial-scm.org/repo/hg/file/tip/mercurial/pythoncapi\_compat.h&gt;)
- mypy &lt;https://github.com/python/mypy&gt; (mypyc, commit &lt;https://github.com/python/mypy/commit/2b7e2df923f7e4a3a199915b3c8563f45bc69dfa&gt;)
- numpy &lt;https://numpy.org/&gt;: pythoncapi-compat Git submodule &lt;https://github.com/numpy/numpy/blob/main/.gitmodules&gt;
- pybluez &lt;https://github.com/pybluez/pybluez&gt; (commit &lt;https://github.com/pybluez/pybluez/commit/5096047f90a1f6a74ceb250aef6243e144170f92&gt;)
- python-snappy &lt;https://github.com/andrix/python-snappy/&gt; (commit &lt;https://github.com/andrix/python-snappy/commit/1a539d71d5b1ceaf9a2291f21f686cf53a46d707&gt;)
- python-zstandard &lt;https://github.com/indygreg/python-zstandard/&gt; uses **Py\_SET\_TYPE()** and **Py\_SET\_SIZE()** (commit &lt;https://github.com/indygreg/python-zstandard/commit/e5a3baf61b65f3075f250f504ddad9f8612bfedf&gt;): Mercurial extension.
- python-zstd &lt;https://github.com/sergey-dryabzhinsky/python-zstd/&gt; (commit &lt;https://github.com/sergey-dryabzhinsky/python-zstd/commit/8aa6d7a4b250e1f0a4e27b4107c39dc516c87f96&gt;)
- hollerith &lt;https://github.com/pyansys/hollerith/&gt; **src/writer.c** uses **PyObject\_CallOneArg() and other Python 3.9 apis** (pythoncapi\_compat.h copy &lt;https://github.com/pyansys/hollerith/blob/main/src/pythoncapi\_compat.h&gt;)
- PyTorch &lt;https://github.com/pytorch/pytorch/&gt; (pythoncapi\_compat.h copy &lt;https://github.com/pytorch/pytorch/blob/main/torch/csrc/utils/pythoncapi\_compat.h&gt;)
- PyGObject &lt;https://gitlab.gnome.org/GNOME/pygobject/&gt; (commit &lt;https://gitlab.gnome.org/GNOME/pygobject/-/commit/074c0348417b87d3003dbb409e6fc26b61121de3&gt;, pythoncapi-compat Meson subproject &lt;https://gitlab.gnome.org/GNOME/pygobject/-/blob/main/subprojects/pythoncapi-compat.wrap?ref\_type=heads&gt;)
- Pillow &lt;https://github.com/python-pillow/Pillow/&gt; (src/thirdparty/pythoncapi\_compat.h &lt;https://github.com/python-pillow/Pillow/blob/main/src/thirdparty/pythoncapi\_compat.h&gt;)
- watchdog &lt;https://github.com/gorakhargosh/watchdog/&gt; (src/pythoncapi\_compat.h &lt;https://github.com/gorakhargosh/watchdog/blob/master/src/pythoncapi\_compat.h&gt;)

## [Projects not using pythoncapi\_compat.h](#Projects_not_using_pythoncapi_compat.h)

Projects not using **pythoncapi\_compat.h**:

•

Cython doesn't use pythoncapi\_compat.h: see Cython issue #3934 &lt;https://github.com/cython/cython/issues/3934&gt;. For example, ModuleSetupCode.c &lt;https://github.com/cython/cython/blob/0.29.x/Cython/Utility/ModuleSetupCode.c&gt; provides functions like **\_\_Pyx\_SET\_REFCNT()**.

Project with a strict contributor agreement:

•

zodbpickle &lt;https://github.com/zopefoundation/zodbpickle/pull/64&gt;

# [RUN TESTS](#RUN_TESTS)

To run pythoncapi-compat tests, type:

```
python3 runtests.py
```

To only test the current Python version, use the **-c** or the **--current** option:

```
python3 runtests.py --current
```

Verbose mode (**-v**, **--verbose**):

```
python3 runtests.py --verbose
```

See tests in the **tests/** subdirectory.

# [CHANGELOG](#CHANGELOG)

- 2026-09-23: **PyUnstable\_Object\_IsUniquelyReferenced()**, **PyUnstable\_TryIncRef()** and **PyUnstable\_EnableTryIncRef()** are no longer available on PyPy. **Py\_REFCNT()** semantics is different on PyPy.
- 2026-09-22: Add support for PyPy3.12 v8.0.0, which provides **PyFrame\_GetCode()** and **PyInterpreterState\_Get()**.
- 2026-09-07: Remove code to support Python 2.7, Python 3.5 and PyPy for Python 2.7 ("pypy2"). Python 2.7 was no longer supported since August 2023. Python 3.5 was no longer supported since October 2024.
- 2026-02-12: Add functions:

•

**PyUnstable\_SetImmortal()**

•

2025-10-14: Add functions:

- **PyTuple\_FromArray()**
- **PyUnstable\_Unicode\_GET\_CACHED\_HASH()**

•

2025-09-18: Add PEP 782 functions:

- **PyBytesWriter\_Create()**
- **PyBytesWriter\_Discard()**
- **PyBytesWriter\_Finish()**
- **PyBytesWriter\_FinishWithPointer()**
- **PyBytesWriter\_FinishWithSize()**
- **PyBytesWriter\_Format()**
- **PyBytesWriter\_GetData()**
- **PyBytesWriter\_GetSize()**
- **PyBytesWriter\_Grow()**
- **PyBytesWriter\_GrowAndUpdatePointer()**
- **PyBytesWriter\_Resize()**
- **PyBytesWriter\_WriteBytes()**

<!--THE END-->

- 2025-09-01: Add **PyUnstable\_Object\_IsUniquelyReferenced()** function.
- 2025-06-09: Add **PyUnicodeWriter\_WriteASCII()** function.
- 2025-06-03: Add functions:

<!--THE END-->

- **PySys\_GetAttr()**
- **PySys\_GetAttrString()**
- **PySys\_GetOptionalAttr()**
- **PySys\_GetOptionalAttrString()**

<!--THE END-->

- 2025-01-19: Add **PyConfig\_Get()** functions.
- 2025-01-06: Add **Py\_fopen()** and **Py\_fclose()** functions.
- 2024-12-16: Add **structmember.h** constants:

<!--THE END-->

- **Py\_T\_BOOL**
- **Py\_T\_BYTE**
- **Py\_T\_CHAR**
- **Py\_T\_DOUBLE**
- **Py\_T\_FLOAT**
- **Py\_T\_INT**
- **Py\_T\_LONGLONG**
- **Py\_T\_LONG**
- **Py\_T\_OBJECT\_EX**
- **Py\_T\_PYSSIZET**
- **Py\_T\_SHORT**
- **Py\_T\_STRING\_INPLACE**
- **Py\_T\_STRING**
- **Py\_T\_UBYTE**
- **Py\_T\_UINT**
- **Py\_T\_ULONGLONG**
- **Py\_T\_ULONG**
- **Py\_T\_USHORT**
- **\_Py\_T\_NONE**
- **\_Py\_T\_OBJECT**
- **Py\_AUDIT\_READ**
- **Py\_READONLY**
- **\_Py\_WRITE\_RESTRICTED**

•

2024-12-13: Add functions and structs:

- **PyLongLayout**
- **PyLong\_GetNativeLayout()**
- **PyLongExport**
- **PyLong\_Export()**
- **PyLong\_FreeExport()**
- **PyLongWriter**
- **PyLongWriter\_Create()**
- **PyLongWriter\_Finish()**
- **PyLongWriter\_Discard()**

•

2024-11-12: Add functions:

- **PyLong\_IsPositive()**
- **PyLong\_IsNegative()**
- **PyLong\_IsZero()**

•

2024-10-09: Add functions:

- **PyBytes\_Join()**
- **PyIter\_NextItem()**
- **PyLong\_AsInt32()**
- **PyLong\_AsInt64()**
- **PyLong\_AsUInt32()**
- **PyLong\_AsUInt64()**
- **PyLong\_FromInt32()**
- **PyLong\_FromInt64()**
- **PyLong\_FromUInt32()**
- **PyLong\_FromUInt64()**
- **PyUnicode\_Equal()**
- **Py\_HashBuffer()**

•

2024-07-18: Add functions:

- **PyUnicodeWriter\_Create()**
- **PyUnicodeWriter\_Discard()**
- **PyUnicodeWriter\_Finish()**
- **PyUnicodeWriter\_WriteChar()**
- **PyUnicodeWriter\_WriteUTF8()**
- **PyUnicodeWriter\_WriteStr()**
- **PyUnicodeWriter\_WriteRepr()**
- **PyUnicodeWriter\_WriteSubstring()**
- **PyUnicodeWriter\_WriteWideChar()**
- **PyUnicodeWriter\_Format()**

<!--THE END-->

- 2024-06-03: Add **PyLong\_GetSign()**.
- 2024-04-23: Drop Python 3.5 support. It cannot be tested anymore (pip fails).
- 2024-04-02: Add **PyDict\_SetDefaultRef()** function.
- 2024-03-29: Add **PyList\_GetItemRef()** function.
- 2024-03-21: Add functions:

<!--THE END-->

- **Py\_GetConstant()**
- **Py\_GetConstantBorrowed()**

•

2024-03-09: Add hash constants:

- **PyHASH\_BITS**
- **PyHASH\_IMAG**
- **PyHASH\_INF**
- **PyHASH\_MODULUS**

•

2024-02-20: Add PyTime API:

- **PyTime\_t** type
- **PyTime\_MIN** and **PyTime\_MAX** constants
- **PyTime\_AsSecondsDouble()**
- **PyTime\_Monotonic()**
- **PyTime\_PerfCounter()**
- **PyTime\_Time()**

<!--THE END-->

- 2023-12-15: Add function **Py\_HashPointer()**.
- 2023-11-14: Add functions:

<!--THE END-->

- **PyDict\_Pop()**
- **PyDict\_PopString()**

•

2023-11-13: Add functions:

- **PyList\_Extend()**
- **PyList\_Clear()**

•

2023-10-04: Add functions:

- **PyUnicode\_EqualToUTF8()**
- **PyUnicode\_EqualToUTF8AndSize()**

•

2023-10-03: Add functions:

- **PyObject\_VisitManagedDict()**
- **PyObject\_ClearManagedDict()**
- **PyThreadState\_GetUnchecked()**

•

2023-09-29: Add functions:

- **PyMapping\_HasKeyWithError()**
- **PyMapping\_HasKeyStringWithError()**
- **PyObject\_HasAttrWithError()**
- **PyObject\_HasAttrStringWithError()**

<!--THE END-->

- 2023-08-25: Add **PyDict\_ContainsString()** and **PyLong\_AsInt()** functions.
- 2023-08-21: Remove support for Python 2.7, Python 3.4 and older.
- 2023-08-16: Add **Py\_IsFinalizing()** function.
- 2023-07-21: Add **PyDict\_GetItemRef()** function.
- 2023-07-18: Add **PyModule\_Add()** function.
- 2023-07-12: Add functions:

<!--THE END-->

- **PyObject\_GetOptionalAttr()**
- **PyObject\_GetOptionalAttrString()**
- **PyMapping\_GetOptionalItem()**
- **PyMapping\_GetOptionalItemString()**

<!--THE END-->

- 2023-07-05: Add **PyObject\_Vectorcall()** function.
- 2023-06-21: Add **PyWeakref\_GetRef()** function.
- 2023-06-20: Add **PyImport\_AddModuleRef()** function.
- 2022-11-15: Add experimental operations to the **upgrade\_pythoncapi.py** script: **Py\_NewRef**, **Py\_CLEAR** and **Py\_SETREF**.
- 2022-11-09: Fix **Py\_SETREF()** and **Py\_XSETREF()** macros for gh-98724 &lt;https://github.com/python/cpython/issues/98724&gt;.
- 2022-11-04: Add **PyFrame\_GetVar()** and **PyFrame\_GetVarString()** functions.
- 2022-08-04: Add **PyCode\_GetVarnames()**, **PyCode\_GetFreevars()** and **PyCode\_GetCellvars()** functions.
- 2022-06-14: Fix compatibility with C++ older than C++11.
- 2022-05-03: Add **PyCode\_GetCode()** function.
- 2022-04-26: Rename the project from **pythoncapi\_compat** to **pythoncapi-compat**: replace the underscore separator with a dash.
- 2022-04-08: Add functions **PyFrame\_GetLocals()**, **PyFrame\_GetGlobals()** **PyFrame\_GetBuiltins()**, and **PyFrame\_GetLasti()**.
- 2022-03-12: Add functions **PyFloat\_Pack2()**, **PyFloat\_Pack4()**, **PyFloat\_Pack8()**, **PyFloat\_Unpack2()**, **PyFloat\_Unpack4()** and **PyFloat\_Unpack8()**.
- 2022-03-03: The project moved to &lt;https://github.com/python/pythoncapi-compat&gt;
- 2022-02-11: The project license changes from the MIT license to the Zero Clause BSD (0BSD) license. Projects copying **pythoncapi\_compat.h** no longer have to include the MIT license and the copyright notice.
- 2022-02-08: Add documentation.
- 2022-02-09: **pythoncapi\_compat.h** now supports C++ on Python 3.6 and newer: use **nullptr** and **reinterpret\_cast&lt;type&gt;** cast on C++, and use **NULL** and **(type)** cast on C.
- 2021-10-15: Add **PyThreadState\_EnterTracing()** and **PyThreadState\_LeaveTracing()**.
- 2021-04-09: Add **Py\_Is()**, **Py\_IsNone()**, **Py\_IsTrue()**, **Py\_IsFalse()** functions.
- 2021-04-01:

<!--THE END-->

- Add **Py\_SETREF()**, **Py\_XSETREF()** and **Py\_UNUSED()**.
- Add PyPy support.

<!--THE END-->

- 2021-01-27: Fix compatibility with Visual Studio 2008 for Python 2.7.
- 2020-11-30: Creation of the **upgrade\_pythoncapi.py** script.
- 2020-06-04: Creation of the **pythoncapi\_compat.h** header file.

# [LINKS](#LINKS)

- Python/C API Reference Manual &lt;https://docs.python.org/dev/c-api/&gt;
- HPy: a better API for Python &lt;https://hpy.readthedocs.io/&gt;
- Cython: C-extensions for Python &lt;https://cython.org/&gt;
- Old 2to3c project &lt;https://github.com/davidmalcolm/2to3c&gt; by David Malcolm which uses Coccinelle &lt;https://coccinelle.gitlabpages.inria.fr/website/&gt; to ease migration of C extensions from Python 2 to Python 3. See also 2to3c: an implementation of Python's 2to3 for C code &lt;https://dmalcolm.livejournal.com/3935.html&gt; article (2009).
- PEPs related to the C API:

<!--THE END-->

- PEP 620 -- Hide implementation details from the C API &lt;https://www.python.org/dev/peps/pep-0620/&gt;
- PEP 670 -- Convert macros to functions in the Python C API &lt;https://www.python.org/dev/peps/pep-0670/&gt;
- PEP 674 -- Disallow using macros as l-values &lt;https://www.python.org/dev/peps/pep-0674/&gt;

•

Make structures opaque

- bpo-39573: PyObject &lt;https://bugs.python.org/issue39573&gt;
- bpo-40170: PyTypeObject &lt;https://bugs.python.org/issue40170&gt;
- bpo-39947: PyThreadState &lt;https://bugs.python.org/issue39947&gt;
- bpo-40421: PyFrameObject &lt;https://bugs.python.org/issue40421&gt;
- bpo-47241: PyCodeObject &lt;https://bugs.python.org/issue47241&gt;

This project is distributed under the Zero Clause BSD (0BSD) license &lt;https://opensource.org/licenses/0BSD&gt; and is covered by the PSF Code of Conduct &lt;https://www.python.org/psf/codeofconduct/&gt;.

# [Author](#Author)

Victor Stinner

# [Copyright](#Copyright)

2022, Victor Stinner

September 29, 2026

---

Document: pythoncapi_compat(1) from pythoncapi-compat 0_git20260929-r0 (Chainguard OS)
Source: https://github.com/python/pythoncapi-compat.git
