From 4c00fd9ef692107165dd34fc36af07ceb7480629 Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Sun, 9 Oct 2016 19:40:15 +0200 Subject: [PATCH] extra python version sanity check at import time Python 3.5 can often import pybind11 modules compiled compiled for Python 3.4 (i.e. all symbols can be resolved), but this leads to crashes later on due to changes in various Python-internal data structures. This commit adds an extra sanity check to prevent a successful import when the Python versions don't match. --- include/pybind11/common.h | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/include/pybind11/common.h b/include/pybind11/common.h index bf5782041..84035eb3f 100644 --- a/include/pybind11/common.h +++ b/include/pybind11/common.h @@ -144,16 +144,28 @@ extern "C" { #define PYBIND11_INTERNALS_ID "__pybind11_" \ PYBIND11_TOSTRING(PYBIND11_VERSION_MAJOR) "_" PYBIND11_TOSTRING(PYBIND11_VERSION_MINOR) "__" -#define PYBIND11_PLUGIN(name) \ - static PyObject *pybind11_init(); \ - PYBIND11_PLUGIN_IMPL(name) { \ - try { \ - return pybind11_init(); \ - } catch (const std::exception &e) { \ - PyErr_SetString(PyExc_ImportError, e.what()); \ - return nullptr; \ - } \ - } \ +#define PYBIND11_PLUGIN(name) \ + static PyObject *pybind11_init(); \ + PYBIND11_PLUGIN_IMPL(name) { \ + int major, minor; \ + if (sscanf(Py_GetVersion(), "%i.%i", &major, &minor) != 2) { \ + PyErr_SetString(PyExc_ImportError, "Can't parse Python version."); \ + return nullptr; \ + } else if (major != PY_MAJOR_VERSION || minor != PY_MINOR_VERSION) { \ + PyErr_Format(PyExc_ImportError, \ + "Python version mismatch: module was compiled for " \ + "version %i.%i, while the interpreter is running " \ + "version %i.%i.", PY_MAJOR_VERSION, PY_MINOR_VERSION, \ + major, minor); \ + return nullptr; \ + } \ + try { \ + return pybind11_init(); \ + } catch (const std::exception &e) { \ + PyErr_SetString(PyExc_ImportError, e.what()); \ + return nullptr; \ + } \ + } \ PyObject *pybind11_init() NAMESPACE_BEGIN(pybind11)