diff --git a/mypyc/lib-rt/vecs/librt_vecs.c b/mypyc/lib-rt/vecs/librt_vecs.c index cad8cbfb23d2..023f1552588d 100644 --- a/mypyc/lib-rt/vecs/librt_vecs.c +++ b/mypyc/lib-rt/vecs/librt_vecs.c @@ -958,7 +958,19 @@ static PyTypeObject *get_vec_type(void) { return &VecType; } +static int +vecs_abi_version(void) { + return LIBRT_VECS_ABI_VERSION; +} + +static int +vecs_api_version(void) { + return LIBRT_VECS_API_VERSION; +} + static VecCapsule Capsule = { + vecs_abi_version, + vecs_api_version, &Vec_TAPI, &Vec_NestedAPI, &Vec_I64API, diff --git a/mypyc/lib-rt/vecs/librt_vecs.h b/mypyc/lib-rt/vecs/librt_vecs.h index d41cc7661482..b7700d4bd9f7 100644 --- a/mypyc/lib-rt/vecs/librt_vecs.h +++ b/mypyc/lib-rt/vecs/librt_vecs.h @@ -10,6 +10,16 @@ #include #include "mypyc_util.h" +// ABI version -- only an exact match is compatible. This will only be changed in +// very exceptional cases (likely never) due to strict backward compatibility +// requirements. +#define LIBRT_VECS_ABI_VERSION 1 + +// API version -- more recent versions must maintain backward compatibility, i.e. +// we can add new features but not remove or change existing features (unless +// ABI version is changed, but see the comment above). +#define LIBRT_VECS_API_VERSION 1 + #ifdef MYPYC_EXPERIMENTAL // Magic (native) integer return value on exception. Caller must also @@ -500,6 +510,8 @@ typedef struct _VecNestedAPI { } VecNestedAPI; typedef struct { + int (*abi_version)(void); + int (*api_version)(void); VecTAPI *t; VecNestedAPI *nested; VecI64API *i64; diff --git a/mypyc/lib-rt/vecs/librt_vecs_api.c b/mypyc/lib-rt/vecs/librt_vecs_api.c index 7ac067ae4161..9993848f3a2e 100644 --- a/mypyc/lib-rt/vecs/librt_vecs_api.c +++ b/mypyc/lib-rt/vecs/librt_vecs_api.c @@ -28,9 +28,28 @@ import_librt_vecs(void) if (mod == NULL) return -1; Py_DECREF(mod); // we import just for the side effect of making the below work. - VecApi = PyCapsule_Import("librt.vecs._C_API", 0); - if (!VecApi) + VecCapsule *capsule = PyCapsule_Import("librt.vecs._C_API", 0); + if (!capsule) return -1; + if (capsule->abi_version() != LIBRT_VECS_ABI_VERSION) { + char err[128]; + snprintf(err, sizeof(err), + "ABI version conflict for librt.vecs, expected %d, found %d", + LIBRT_VECS_ABI_VERSION, + capsule->abi_version()); + PyErr_SetString(PyExc_ValueError, err); + return -1; + } + if (capsule->api_version() < LIBRT_VECS_API_VERSION) { + char err[128]; + snprintf(err, sizeof(err), + "API version conflict for librt.vecs, expected %d or newer, found %d (hint: upgrade librt)", + LIBRT_VECS_API_VERSION, + capsule->api_version()); + PyErr_SetString(PyExc_ValueError, err); + return -1; + } + VecApi = capsule; VecI64Api = *VecApi->i64; VecI32Api = *VecApi->i32; VecI16Api = *VecApi->i16;