mirror of
https://github.com/python/cpython.git
synced 2025-10-27 19:54:38 +00:00
gh-137210: Add a struct, slot & function for checking an extension's ABI (GH-137212)
Co-authored-by: Steve Dower <steve.dower@microsoft.com>
This commit is contained in:
parent
c1a9c23195
commit
0c74fc8af0
24 changed files with 654 additions and 8 deletions
|
|
@ -4,6 +4,7 @@
|
|||
#include "Python.h"
|
||||
#include "pycore_abstract.h" // _PyIndex_Check()
|
||||
#include "pycore_object.h" // _PyType_IsReady()
|
||||
#include "pycore_unicodeobject.h" // _PyUnicodeWriter_FormatV()
|
||||
|
||||
typedef double va_double;
|
||||
|
||||
|
|
@ -668,6 +669,116 @@ PyModule_AddType(PyObject *module, PyTypeObject *type)
|
|||
return PyModule_AddObjectRef(module, name, (PyObject *)type);
|
||||
}
|
||||
|
||||
static int _abiinfo_raise(const char *module_name, const char *format, ...)
|
||||
{
|
||||
PyUnicodeWriter *writer = PyUnicodeWriter_Create(0);
|
||||
if (!writer) {
|
||||
return -1;
|
||||
}
|
||||
if (module_name) {
|
||||
if (PyUnicodeWriter_WriteUTF8(writer, module_name, -1) < 0) {
|
||||
PyUnicodeWriter_Discard(writer);
|
||||
return -1;
|
||||
}
|
||||
if (PyUnicodeWriter_WriteASCII(writer, ": ", 2) < 0) {
|
||||
PyUnicodeWriter_Discard(writer);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
va_list vargs;
|
||||
va_start(vargs, format);
|
||||
if (_PyUnicodeWriter_FormatV(writer, format, vargs) < 0) {
|
||||
PyUnicodeWriter_Discard(writer);
|
||||
return -1;
|
||||
}
|
||||
PyObject *message = PyUnicodeWriter_Finish(writer);
|
||||
if (!message) {
|
||||
return -1;
|
||||
}
|
||||
PyErr_SetObject(PyExc_ImportError, message);
|
||||
Py_DECREF(message);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int PyABIInfo_Check(PyABIInfo *info, const char *module_name)
|
||||
{
|
||||
if (!info) {
|
||||
return _abiinfo_raise(module_name, "NULL PyABIInfo");
|
||||
}
|
||||
|
||||
/* abiinfo_major_version */
|
||||
if (info->abiinfo_major_version == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (info->abiinfo_major_version > 1) {
|
||||
return _abiinfo_raise(module_name, "PyABIInfo version too high");
|
||||
}
|
||||
|
||||
/* Internal ABI */
|
||||
if (info->flags & PyABIInfo_INTERNAL) {
|
||||
if (info->abi_version && (info->abi_version != PY_VERSION_HEX)) {
|
||||
return _abiinfo_raise(
|
||||
module_name,
|
||||
"incompatible internal ABI (0x%x != 0x%x)",
|
||||
info->abi_version, PY_VERSION_HEX);
|
||||
}
|
||||
}
|
||||
|
||||
#define XY_MASK 0xffff0000
|
||||
if (info->flags & PyABIInfo_STABLE) {
|
||||
/* Greater-than major.minor version check */
|
||||
if (info->abi_version) {
|
||||
if ((info->abi_version & XY_MASK) > (PY_VERSION_HEX & XY_MASK)) {
|
||||
return _abiinfo_raise(
|
||||
module_name,
|
||||
"incompatible future stable ABI version (%d.%d)",
|
||||
((info->abi_version) >> 24) % 0xff,
|
||||
((info->abi_version) >> 16) % 0xff);
|
||||
}
|
||||
if (info->abi_version < Py_PACK_VERSION(3, 2)) {
|
||||
return _abiinfo_raise(
|
||||
module_name,
|
||||
"invalid stable ABI version (%d.%d)",
|
||||
((info->abi_version) >> 24) % 0xff,
|
||||
((info->abi_version) >> 16) % 0xff);
|
||||
}
|
||||
}
|
||||
if (info->flags & PyABIInfo_INTERNAL) {
|
||||
return _abiinfo_raise(module_name,
|
||||
"cannot use both internal and stable ABI");
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Exact major.minor version check */
|
||||
if (info->abi_version) {
|
||||
if ((info->abi_version & XY_MASK) != (PY_VERSION_HEX & XY_MASK)) {
|
||||
return _abiinfo_raise(
|
||||
module_name,
|
||||
"incompatible ABI version (%d.%d)",
|
||||
((info->abi_version) >> 24) % 0xff,
|
||||
((info->abi_version) >> 16) % 0xff);
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef XY_MASK
|
||||
|
||||
/* Free-threading/GIL */
|
||||
uint16_t gilflags = info->flags & (PyABIInfo_GIL | PyABIInfo_FREETHREADED);
|
||||
#if Py_GIL_DISABLED
|
||||
if (gilflags == PyABIInfo_GIL) {
|
||||
return _abiinfo_raise(module_name,
|
||||
"incompatible with free-threaded CPython");
|
||||
}
|
||||
#else
|
||||
if (gilflags == PyABIInfo_FREETHREADED) {
|
||||
return _abiinfo_raise(module_name,
|
||||
"only compatible with free-threaded CPython");
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Exported functions for version helper macros */
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue