# Python ABIs and PEP 703

**URL:** <https://discuss.python.org/t/python-abis-and-pep-703/34018>\
**Category:** Core Development\
**Created:** [September 18, 2023, 2:59pm UTC](https://discuss.python.org/t/python-abis-and-pep-703/34018 "2023-09-18T14:59:39Z")\
**Posts on this page:** 1\
**Showing post:** 27

<div class="post-metadata">

**Author:** ![colesbury](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/colesbury/32/28031_2.png) [@colesbury](https://discuss.python.org/u/colesbury)\
**Post date:** [September 21, 2023, 8:03pm UTC](https://discuss.python.org/t/python-abis-and-pep-703/34018/27 "2023-09-21T20:03:31Z")

</div>

Building on @encukou’s comments, here’s a modification of the original proposal. (Don’t focus too much on naming, we can work out those details later.)

Here’s a prototype: [Prototype ABI4 with Python 3.7+ compatibility · colesbury/cpython@2c1d02a · GitHub](https://github.com/colesbury/cpython/commit/2c1d02a85ac3b41c545d1089f7439b108059cb53)

- We add a new “abi4” with targets “cp37-abi4”, …, “cp313-abi4”.
- C extensions can target by “abi4” by defining `Py_ABI_VERSION_4` along with the usual `Py_LIMITED_API=0x30...`
- The `--disable-gil` builds can load “abi4” wheels, but not “abi3” wheels. So “cp37-abi4” wheels are compatible with Python 3.7+, including `--disable-gil` builds.
- `PyObject` and `PyVarObject` become opaque structs in abi4.
- `PyObject_HEAD` is still [needed](https://github.com/s-ball/pyrbtree/blob/3809d898e61e4417c102af0cde547ed229833a02/pyrbtree/_rbtree/_rbtree.c#L29) for extensions to define their own types. In abi4, it [reserves](https://github.com/colesbury/cpython/blob/2c1d02a85ac3b41c545d1089f7439b108059cb53/Include/object.h#L69) enough space for both abi3 PyObject headers and `--disable-gil` PyObject headers. This means 24 or 32 bytes on 32-bit or 64-bit platforms. Note that _extra_ space in the header is fine.
- `PyModuleDef` is a bit different. It [reserves](https://github.com/colesbury/cpython/blob/2c1d02a85ac3b41c545d1089f7439b108059cb53/Include/moduleobject.h#L40) exactly the space for an abi3 PyObject header. (It can’t be bigger because older versions of CPython still need to access the fields.) At the API level, [`PyModuleDef_Init`](https://docs.python.org/3/c-api/module.html#c.PyModuleDef_Init) no longer guarantees that it returns “def cast to `PyObject*`”. Old versions of CPython, of course, still do this as does the default build of CPython 3.13. The `--disable-gil` builds [return a simple wrapper](https://github.com/colesbury/cpython/blob/2c1d02a85ac3b41c545d1089f7439b108059cb53/Objects/moduleobject.c#L55-L72).

The implementations of `Py_TYPE` and similar require special care when targeting pre-3.13 versions of Python and ABI 4. (See [this file](https://github.com/colesbury/cpython/blob/2c1d02a85ac3b41c545d1089f7439b108059cb53/Include/abi4_compat.h)).

- Extensions must call the `Py_Type` function in 3.13, but that won’t be available in 3.12 and older. When loaded on those versions, the extension must [access the field directly](https://github.com/colesbury/cpython/blob/2c1d02a85ac3b41c545d1089f7439b108059cb53/Include/abi4_compat.h#L52).
- On most platforms, we handle this by making `Py_Type` a weak symbol. Windows doesn’t support weak symbols, so we use `GetProcAddress` instead to determine if `Py_Type` is available.
- There’s a [dispatcher mechanism](https://github.com/colesbury/cpython/blob/2c1d02a85ac3b41c545d1089f7439b108059cb53/Include/abi4_compat.h#L91-L97) so that we only have to look up the symbol on the first invocation.

Risks and weird stuff

- Wheels can be named like `cryptography-42.0.0-cp37-abi4-[platform].whl` but the actual shared libraries will still need to be named with the `.abi3.so` extension to be loadable by older versions of Python.
- pip (or more specifically pypa/packaging) will needed to disallow abi3 wheels from `--disable-gil` builds and allow `abi4` wheels for Python 3.7+.

---

_[View the full topic](https://discuss.python.org/t/python-abis-and-pep-703/34018)._
