Porting to ABI v14
Note
This section is a work-in-progress and will be continually updated while ABI v14 is considered experimental.
This section is intended to help bindings authors port their projects to target ABI v14. The strongest motivation for doing so is to be able to create extension modules that are able to take advantage of multiple interpreters and free-threading.
Overview
PEP 489 (multi-phase initialisation)
PEP 573 (module states)
opaque and mutable vs public and immutable
API porting definitions.
.sip Specification File Changes from v13 and v12
This section summarises the differences in .sip specification files
(including handwritten code) between v14 and older versions.
All handwritten implementations of
__hash__()must returnPy_hash_t.All handwritten implementations of
__len__()must returnPy_ssize_t.%AccessCodeis not supported.%GetCodeshould be used instead.The concept of delayed dtors is no longer supported. The
DelayDtorclass annotation is ignored.The deprecated
sipIsErrerror flag is not supported.
API Changes from v13 and v12
This section summarises the differences between the v14 API and older versions.
The
sipSimpleWrapper,sipWrapperandsipWrapperTypeC types are now always opaque, even if the limited C API is not used.sipGetBufferInfo(),sipReleaseBufferInfo()andsipBufferInfoDefare no longer supported as the corresponding Python support is now part of the stable ABI.sipConvertFromEnum()is passed a pointer to the enum’s value rather than the value itself.sipConvertToBool()now returned a C/C++boolrather than anint.PyErr_Occurred()must be called to check if the conversion was successful.sipConvertToEnum()is passed a pointer to return the enum’s value rather than returning the value from the function itself.sipEnableAutoconversion()is passed the Python type object rather than the generated type structure.sipExportSymbol()has been replaced bysipExportSymbols().sipGetDate(),sipGetDateTime()andsipGetTime()now return-1if there was an error.sipGetFrame()has been replaced bysipGetFrameRef().sipGetInterpreter()has been replaced bysipGetInterpreterView().sipGetPyObject()has been replaced bysipGetPyObjectRef().sipGetTypeUserData()has been replaced bysipGetTypeUserObject().sipInstanceDestroyed()now takes a pointer to aPyObject *(rather than just aPyObject *) which will be set toNULLwhen the call returns.sipParseResult()has additional arguments that are provided by%VirtualCatcherCode. TheSformat character is no longer supported.sipPrintObject()has been replaced bysipObjectDump().sipPyTypeDict()has been removed, usesipPyTypeDictRef()instead.sipPyTypeName()has been removed, use(const char *)PyType_GetSlot(type, Py_tp_name)instead.sipRegisterAttributeGetter()is no longer supported. A handler for thesipEventFinalisingTypeevent type should be used instead.sipRegisterProxyResolver()is no longer supported. A handler for thesipEventFinalisingAddressevent type should be used instead.sipRegisterEventHandler()has been replaced bysipRegisterEventHandlers().sipRegisterExitNotifier()is no longer supported. A handler for thesipEventCollectingModuleevent type should be used instead.sipResolveTypedef()returns a pointer to the name being resolved (rather than NULL) if the name doesn’t correspond to the name of a typedef.sipSetDestroyOnExit()is no longer supported.sipSetTypeUserData()has been replaced bysipSetTypeUserObject().sipSimpleWrapper_Typeis no longer supported, callsipGetSimpleWrapperType()instead.sipTypeAsPyTypeObject()has been replaced bysipGetPyTypeRef().sipTypeIsNamespace()is no longer supported.sipTypeName()is no longer supported. Calls tosipGetPyTypeRef()andPyType_GetSlot()should be used instead.sipVoidPtr_Typeis no longer supported, callsipGetVoidPtrType()instead.sipWrapper_Typeis no longer supported, callsipGetWrapperType()instead.sipWrapperType_Typeis no longer supported, callsipGetWrapperTypeType()instead.
A Case Study
In this section we outline the steps taken to add ABI v14 as a target to two large projects, specifically PyQt5 (which currently targets ABI v12) and PyQt6 (which currently targets ABI v13). We are adding the new target, rather than replacing the existing one, because we still need to build the project against versions of Python prior to v3.15.