From cfb718592bfe087e2996ce8442952447ad0bd931 Mon Sep 17 00:00:00 2001 From: Amit Patankar Date: Wed, 20 Feb 2019 11:47:55 -0800 Subject: [PATCH 01/12] Wrapping exception logic in #ifdefs to allow for compilation without exceptions. --- include/pybind11/detail/common.h | 66 ++++++++++++++++++++++++----- include/pybind11/detail/internals.h | 2 + include/pybind11/pybind11.h | 4 ++ 3 files changed, 61 insertions(+), 11 deletions(-) diff --git a/include/pybind11/detail/common.h b/include/pybind11/detail/common.h index 5ff74856b1..45f2df375c 100644 --- a/include/pybind11/detail/common.h +++ b/include/pybind11/detail/common.h @@ -263,6 +263,36 @@ extern "C" { } \ PyObject *pybind11_init() +bool Py_VersionCheckPassed() { + int major, minor; + if (sscanf(Py_GetVersion(), "%i.%i", &major, &minor) != 2) { + PyErr_SetString(PyExc_ImportError, "Can't parse Python version."); + return false; + } + 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 false; + } + return true; +} + +// Returns nullptr on an error. +#define GET_PYBIND11_MODULE(pybind11_init_, name, module) \ + try { \ + PYBIND11_CONCAT(pybind11_init_, name)(module); \ + return module.ptr(); \ + } catch (pybind11::error_already_set & e) { \ + PyErr_SetString(PyExc_ImportError, e.what()); \ + return nullptr; \ + } catch (const std::exception &e) { \ + PyErr_SetString(PyExc_ImportError, e.what()); \ + return nullptr; \ + } + /** \rst This macro creates the entry point that will be invoked when the Python interpreter imports an extension module. The module name is given as the fist argument and it @@ -280,17 +310,31 @@ extern "C" { }); } \endrst */ -#define PYBIND11_MODULE(name, variable) \ - static void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &); \ - PYBIND11_PLUGIN_IMPL(name) { \ - PYBIND11_CHECK_PYTHON_VERSION \ - auto m = pybind11::module(PYBIND11_TOSTRING(name)); \ - try { \ - PYBIND11_CONCAT(pybind11_init_, name)(m); \ - return m.ptr(); \ - } PYBIND11_CATCH_INIT_EXCEPTIONS \ - } \ - void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &variable) + +#if defined(PYBIND11_NOEXCEPTIONS) +#define PYBIND11_MODULE(name, variable) \ + static void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &); \ + PYBIND11_PLUGIN_IMPL(name) { \ + if (!Py_VersionCheckPassed()) { \ + return nullptr; \ + } \ + auto m = pybind11::module(PYBIND11_TOSTRING(name)); \ + PYBIND11_CONCAT(pybind11_init_, name)(m); \ + return m.ptr(); \ + } \ + void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module & variable) +#else +#define PYBIND11_MODULE(name, variable) \ + static void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &); \ + PYBIND11_PLUGIN_IMPL(name) { \ + if (!Py_VersionCheckPassed()) { \ + return nullptr; \ + } \ + auto m = pybind11::module(PYBIND11_TOSTRING(name)); \ + GET_PYBIND11_MODULE(pybind11_init_, name, m); \ + } \ + void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module & variable) +#endif NAMESPACE_BEGIN(PYBIND11_NAMESPACE) diff --git a/include/pybind11/detail/internals.h b/include/pybind11/detail/internals.h index 6d7dc5cfe9..a1b753f36d 100644 --- a/include/pybind11/detail/internals.h +++ b/include/pybind11/detail/internals.h @@ -215,6 +215,7 @@ PYBIND11_NOINLINE inline internals &get_internals() { builtins[id] = capsule(internals_pp); internals_ptr->registered_exception_translators.push_front( [](std::exception_ptr p) -> void { +#if !defined(PYBIND11_NOEXCEPTIONS) try { if (p) std::rethrow_exception(p); } catch (error_already_set &e) { e.restore(); return; @@ -230,6 +231,7 @@ PYBIND11_NOINLINE inline internals &get_internals() { PyErr_SetString(PyExc_RuntimeError, "Caught an unknown exception!"); return; } +#endif } ); internals_ptr->static_property_type = make_static_property_type(); diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 7fa0f0e176..31cdc44d55 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -661,7 +661,9 @@ class cpp_function : public function { } } } catch (error_already_set &e) { +#if !defined(PYBIND11_NOEXCEPTIONS) e.restore(); +#endif return nullptr; } catch (...) { /* When an exception is caught, give each registered exception @@ -1784,6 +1786,7 @@ NAMESPACE_END(detail) * This is intended for simple exception translations; for more complex translation, register the * exception object and translator directly. */ +#if !defined(PYBIND11_NOEXCEPTIONS) template exception ®ister_exception(handle scope, const char *name, @@ -1801,6 +1804,7 @@ exception ®ister_exception(handle scope, }); return ex; } +#endif NAMESPACE_BEGIN(detail) PYBIND11_NOINLINE inline void print(tuple args, dict kwargs) { From 453663e5aff99f8c8baeec6c5f2da0bb979283ef Mon Sep 17 00:00:00 2001 From: Amit Patankar Date: Wed, 20 Feb 2019 16:19:11 -0800 Subject: [PATCH 02/12] Moving the Py_VersionCheckPassed function to the pybind11 namespace. --- include/pybind11/detail/common.h | 38 ++++++++++++++++---------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/include/pybind11/detail/common.h b/include/pybind11/detail/common.h index 45f2df375c..3ec1f8ea2a 100644 --- a/include/pybind11/detail/common.h +++ b/include/pybind11/detail/common.h @@ -263,23 +263,6 @@ extern "C" { } \ PyObject *pybind11_init() -bool Py_VersionCheckPassed() { - int major, minor; - if (sscanf(Py_GetVersion(), "%i.%i", &major, &minor) != 2) { - PyErr_SetString(PyExc_ImportError, "Can't parse Python version."); - return false; - } - 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 false; - } - return true; -} - // Returns nullptr on an error. #define GET_PYBIND11_MODULE(pybind11_init_, name, module) \ try { \ @@ -315,7 +298,7 @@ bool Py_VersionCheckPassed() { #define PYBIND11_MODULE(name, variable) \ static void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &); \ PYBIND11_PLUGIN_IMPL(name) { \ - if (!Py_VersionCheckPassed()) { \ + if (!pybind11::Py_VersionCheckPassed()) { \ return nullptr; \ } \ auto m = pybind11::module(PYBIND11_TOSTRING(name)); \ @@ -327,7 +310,7 @@ bool Py_VersionCheckPassed() { #define PYBIND11_MODULE(name, variable) \ static void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &); \ PYBIND11_PLUGIN_IMPL(name) { \ - if (!Py_VersionCheckPassed()) { \ + if (!pybind11::Py_VersionCheckPassed()) { \ return nullptr; \ } \ auto m = pybind11::module(PYBIND11_TOSTRING(name)); \ @@ -342,6 +325,23 @@ NAMESPACE_BEGIN(PYBIND11_NAMESPACE) using ssize_t = Py_ssize_t; using size_t = std::size_t; +bool Py_VersionCheckPassed() { + int major, minor; + if (sscanf(Py_GetVersion(), "%i.%i", &major, &minor) != 2) { + PyErr_SetString(PyExc_ImportError, "Can't parse Python version."); + return false; + } + 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 false; + } + return true; +} + /// Approach used to cast a previously unknown C++ instance into a Python object enum class return_value_policy : uint8_t { /** This is the default return value policy, which falls back to the policy From d6421200090f2c502b255e35c63d203a53812f78 Mon Sep 17 00:00:00 2001 From: Amit Patankar Date: Wed, 20 Feb 2019 17:04:27 -0800 Subject: [PATCH 03/12] Making the version function an inline function and adding it to the detail namespace. --- include/pybind11/detail/common.h | 38 ++++++++++++++++---------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/include/pybind11/detail/common.h b/include/pybind11/detail/common.h index 3ec1f8ea2a..5908c940c3 100644 --- a/include/pybind11/detail/common.h +++ b/include/pybind11/detail/common.h @@ -298,7 +298,7 @@ extern "C" { #define PYBIND11_MODULE(name, variable) \ static void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &); \ PYBIND11_PLUGIN_IMPL(name) { \ - if (!pybind11::Py_VersionCheckPassed()) { \ + if (!pybind11::detail::Py_VersionCheckPassed()) { \ return nullptr; \ } \ auto m = pybind11::module(PYBIND11_TOSTRING(name)); \ @@ -310,7 +310,7 @@ extern "C" { #define PYBIND11_MODULE(name, variable) \ static void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &); \ PYBIND11_PLUGIN_IMPL(name) { \ - if (!pybind11::Py_VersionCheckPassed()) { \ + if (!pybind11::detail::Py_VersionCheckPassed()) { \ return nullptr; \ } \ auto m = pybind11::module(PYBIND11_TOSTRING(name)); \ @@ -325,23 +325,6 @@ NAMESPACE_BEGIN(PYBIND11_NAMESPACE) using ssize_t = Py_ssize_t; using size_t = std::size_t; -bool Py_VersionCheckPassed() { - int major, minor; - if (sscanf(Py_GetVersion(), "%i.%i", &major, &minor) != 2) { - PyErr_SetString(PyExc_ImportError, "Can't parse Python version."); - return false; - } - 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 false; - } - return true; -} - /// Approach used to cast a previously unknown C++ instance into a Python object enum class return_value_policy : uint8_t { /** This is the default return value policy, which falls back to the policy @@ -413,6 +396,23 @@ constexpr size_t instance_simple_holder_in_ptrs() { return size_in_ptrs(sizeof(std::shared_ptr)); } +inline bool Py_VersionCheckPassed() { + int major, minor; + if (sscanf(Py_GetVersion(), "%i.%i", &major, &minor) != 2) { + PyErr_SetString(PyExc_ImportError, "Can't parse Python version."); + return false; + } + 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 false; + } + return true; +} + // Forward declarations struct type_info; struct value_and_holder; From 4fa14c5f91f42d2b5f60d96b5ac8208b9bab6fc6 Mon Sep 17 00:00:00 2001 From: Amit Patankar Date: Thu, 25 Apr 2019 16:49:58 -0700 Subject: [PATCH 04/12] Trigger CI. From 5540fad8cb1d57d9df6c1d5f41182fc2d57a3d87 Mon Sep 17 00:00:00 2001 From: Amit Patankar Date: Fri, 26 Apr 2019 09:54:10 -0700 Subject: [PATCH 05/12] Test presubmits again. From 4f49b322f30bfd4a6ff3a4e1eeb3dcd91b6bcc7a Mon Sep 17 00:00:00 2001 From: Amit Patankar Date: Wed, 20 Feb 2019 11:47:55 -0800 Subject: [PATCH 06/12] Wrapping exception logic in #ifdefs to allow for compilation without exceptions. --- include/pybind11/detail/common.h | 66 ++++++++++++++++++++++++----- include/pybind11/detail/internals.h | 2 + include/pybind11/pybind11.h | 4 ++ 3 files changed, 61 insertions(+), 11 deletions(-) diff --git a/include/pybind11/detail/common.h b/include/pybind11/detail/common.h index 5ff74856b1..45f2df375c 100644 --- a/include/pybind11/detail/common.h +++ b/include/pybind11/detail/common.h @@ -263,6 +263,36 @@ extern "C" { } \ PyObject *pybind11_init() +bool Py_VersionCheckPassed() { + int major, minor; + if (sscanf(Py_GetVersion(), "%i.%i", &major, &minor) != 2) { + PyErr_SetString(PyExc_ImportError, "Can't parse Python version."); + return false; + } + 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 false; + } + return true; +} + +// Returns nullptr on an error. +#define GET_PYBIND11_MODULE(pybind11_init_, name, module) \ + try { \ + PYBIND11_CONCAT(pybind11_init_, name)(module); \ + return module.ptr(); \ + } catch (pybind11::error_already_set & e) { \ + PyErr_SetString(PyExc_ImportError, e.what()); \ + return nullptr; \ + } catch (const std::exception &e) { \ + PyErr_SetString(PyExc_ImportError, e.what()); \ + return nullptr; \ + } + /** \rst This macro creates the entry point that will be invoked when the Python interpreter imports an extension module. The module name is given as the fist argument and it @@ -280,17 +310,31 @@ extern "C" { }); } \endrst */ -#define PYBIND11_MODULE(name, variable) \ - static void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &); \ - PYBIND11_PLUGIN_IMPL(name) { \ - PYBIND11_CHECK_PYTHON_VERSION \ - auto m = pybind11::module(PYBIND11_TOSTRING(name)); \ - try { \ - PYBIND11_CONCAT(pybind11_init_, name)(m); \ - return m.ptr(); \ - } PYBIND11_CATCH_INIT_EXCEPTIONS \ - } \ - void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &variable) + +#if defined(PYBIND11_NOEXCEPTIONS) +#define PYBIND11_MODULE(name, variable) \ + static void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &); \ + PYBIND11_PLUGIN_IMPL(name) { \ + if (!Py_VersionCheckPassed()) { \ + return nullptr; \ + } \ + auto m = pybind11::module(PYBIND11_TOSTRING(name)); \ + PYBIND11_CONCAT(pybind11_init_, name)(m); \ + return m.ptr(); \ + } \ + void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module & variable) +#else +#define PYBIND11_MODULE(name, variable) \ + static void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &); \ + PYBIND11_PLUGIN_IMPL(name) { \ + if (!Py_VersionCheckPassed()) { \ + return nullptr; \ + } \ + auto m = pybind11::module(PYBIND11_TOSTRING(name)); \ + GET_PYBIND11_MODULE(pybind11_init_, name, m); \ + } \ + void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module & variable) +#endif NAMESPACE_BEGIN(PYBIND11_NAMESPACE) diff --git a/include/pybind11/detail/internals.h b/include/pybind11/detail/internals.h index 6d7dc5cfe9..a1b753f36d 100644 --- a/include/pybind11/detail/internals.h +++ b/include/pybind11/detail/internals.h @@ -215,6 +215,7 @@ PYBIND11_NOINLINE inline internals &get_internals() { builtins[id] = capsule(internals_pp); internals_ptr->registered_exception_translators.push_front( [](std::exception_ptr p) -> void { +#if !defined(PYBIND11_NOEXCEPTIONS) try { if (p) std::rethrow_exception(p); } catch (error_already_set &e) { e.restore(); return; @@ -230,6 +231,7 @@ PYBIND11_NOINLINE inline internals &get_internals() { PyErr_SetString(PyExc_RuntimeError, "Caught an unknown exception!"); return; } +#endif } ); internals_ptr->static_property_type = make_static_property_type(); diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 7fa0f0e176..31cdc44d55 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -661,7 +661,9 @@ class cpp_function : public function { } } } catch (error_already_set &e) { +#if !defined(PYBIND11_NOEXCEPTIONS) e.restore(); +#endif return nullptr; } catch (...) { /* When an exception is caught, give each registered exception @@ -1784,6 +1786,7 @@ NAMESPACE_END(detail) * This is intended for simple exception translations; for more complex translation, register the * exception object and translator directly. */ +#if !defined(PYBIND11_NOEXCEPTIONS) template exception ®ister_exception(handle scope, const char *name, @@ -1801,6 +1804,7 @@ exception ®ister_exception(handle scope, }); return ex; } +#endif NAMESPACE_BEGIN(detail) PYBIND11_NOINLINE inline void print(tuple args, dict kwargs) { From ed773c1bf220f29b723ec6835e1845cb9e7224c9 Mon Sep 17 00:00:00 2001 From: Amit Patankar Date: Wed, 20 Feb 2019 16:19:11 -0800 Subject: [PATCH 07/12] Moving the Py_VersionCheckPassed function to the pybind11 namespace. --- include/pybind11/detail/common.h | 38 ++++++++++++++++---------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/include/pybind11/detail/common.h b/include/pybind11/detail/common.h index 45f2df375c..3ec1f8ea2a 100644 --- a/include/pybind11/detail/common.h +++ b/include/pybind11/detail/common.h @@ -263,23 +263,6 @@ extern "C" { } \ PyObject *pybind11_init() -bool Py_VersionCheckPassed() { - int major, minor; - if (sscanf(Py_GetVersion(), "%i.%i", &major, &minor) != 2) { - PyErr_SetString(PyExc_ImportError, "Can't parse Python version."); - return false; - } - 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 false; - } - return true; -} - // Returns nullptr on an error. #define GET_PYBIND11_MODULE(pybind11_init_, name, module) \ try { \ @@ -315,7 +298,7 @@ bool Py_VersionCheckPassed() { #define PYBIND11_MODULE(name, variable) \ static void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &); \ PYBIND11_PLUGIN_IMPL(name) { \ - if (!Py_VersionCheckPassed()) { \ + if (!pybind11::Py_VersionCheckPassed()) { \ return nullptr; \ } \ auto m = pybind11::module(PYBIND11_TOSTRING(name)); \ @@ -327,7 +310,7 @@ bool Py_VersionCheckPassed() { #define PYBIND11_MODULE(name, variable) \ static void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &); \ PYBIND11_PLUGIN_IMPL(name) { \ - if (!Py_VersionCheckPassed()) { \ + if (!pybind11::Py_VersionCheckPassed()) { \ return nullptr; \ } \ auto m = pybind11::module(PYBIND11_TOSTRING(name)); \ @@ -342,6 +325,23 @@ NAMESPACE_BEGIN(PYBIND11_NAMESPACE) using ssize_t = Py_ssize_t; using size_t = std::size_t; +bool Py_VersionCheckPassed() { + int major, minor; + if (sscanf(Py_GetVersion(), "%i.%i", &major, &minor) != 2) { + PyErr_SetString(PyExc_ImportError, "Can't parse Python version."); + return false; + } + 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 false; + } + return true; +} + /// Approach used to cast a previously unknown C++ instance into a Python object enum class return_value_policy : uint8_t { /** This is the default return value policy, which falls back to the policy From 65dca2c5c8e71d77b26d9b3a417da805aecf9bd4 Mon Sep 17 00:00:00 2001 From: Amit Patankar Date: Wed, 20 Feb 2019 17:04:27 -0800 Subject: [PATCH 08/12] Making the version function an inline function and adding it to the detail namespace. --- include/pybind11/detail/common.h | 38 ++++++++++++++++---------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/include/pybind11/detail/common.h b/include/pybind11/detail/common.h index 3ec1f8ea2a..5908c940c3 100644 --- a/include/pybind11/detail/common.h +++ b/include/pybind11/detail/common.h @@ -298,7 +298,7 @@ extern "C" { #define PYBIND11_MODULE(name, variable) \ static void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &); \ PYBIND11_PLUGIN_IMPL(name) { \ - if (!pybind11::Py_VersionCheckPassed()) { \ + if (!pybind11::detail::Py_VersionCheckPassed()) { \ return nullptr; \ } \ auto m = pybind11::module(PYBIND11_TOSTRING(name)); \ @@ -310,7 +310,7 @@ extern "C" { #define PYBIND11_MODULE(name, variable) \ static void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &); \ PYBIND11_PLUGIN_IMPL(name) { \ - if (!pybind11::Py_VersionCheckPassed()) { \ + if (!pybind11::detail::Py_VersionCheckPassed()) { \ return nullptr; \ } \ auto m = pybind11::module(PYBIND11_TOSTRING(name)); \ @@ -325,23 +325,6 @@ NAMESPACE_BEGIN(PYBIND11_NAMESPACE) using ssize_t = Py_ssize_t; using size_t = std::size_t; -bool Py_VersionCheckPassed() { - int major, minor; - if (sscanf(Py_GetVersion(), "%i.%i", &major, &minor) != 2) { - PyErr_SetString(PyExc_ImportError, "Can't parse Python version."); - return false; - } - 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 false; - } - return true; -} - /// Approach used to cast a previously unknown C++ instance into a Python object enum class return_value_policy : uint8_t { /** This is the default return value policy, which falls back to the policy @@ -413,6 +396,23 @@ constexpr size_t instance_simple_holder_in_ptrs() { return size_in_ptrs(sizeof(std::shared_ptr)); } +inline bool Py_VersionCheckPassed() { + int major, minor; + if (sscanf(Py_GetVersion(), "%i.%i", &major, &minor) != 2) { + PyErr_SetString(PyExc_ImportError, "Can't parse Python version."); + return false; + } + 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 false; + } + return true; +} + // Forward declarations struct type_info; struct value_and_holder; From 7184def53d5a432897cdd15dad77fd42f5c406a5 Mon Sep 17 00:00:00 2001 From: Amit Patankar Date: Thu, 30 May 2019 14:33:07 -0700 Subject: [PATCH 09/12] Applying the no exception logic to the new plugins and extending it to the deprecated PYBIND11_PLUGIN as well. --- include/pybind11/detail/common.h | 70 ++++++++++++++------------------ 1 file changed, 31 insertions(+), 39 deletions(-) diff --git a/include/pybind11/detail/common.h b/include/pybind11/detail/common.h index 5908c940c3..2e57f20d19 100644 --- a/include/pybind11/detail/common.h +++ b/include/pybind11/detail/common.h @@ -252,6 +252,16 @@ extern "C" { return m.ptr(); } \endrst */ +#if defined(PYBIND11_NOEXCEPTIONS) +#define PYBIND11_PLUGIN(name) \ + PYBIND11_DEPRECATED("PYBIND11_PLUGIN is deprecated, use PYBIND11_MODULE") \ + static PyObject *pybind11_init(); \ + PYBIND11_PLUGIN_IMPL(name) { \ + PYBIND11_CHECK_PYTHON_VERSION \ + return pybind11_init(); \ + } \ + PyObject *pybind11_init() +#else #define PYBIND11_PLUGIN(name) \ PYBIND11_DEPRECATED("PYBIND11_PLUGIN is deprecated, use PYBIND11_MODULE") \ static PyObject *pybind11_init(); \ @@ -262,6 +272,7 @@ extern "C" { } PYBIND11_CATCH_INIT_EXCEPTIONS \ } \ PyObject *pybind11_init() +#endif // Returns nullptr on an error. #define GET_PYBIND11_MODULE(pybind11_init_, name, module) \ @@ -293,30 +304,28 @@ extern "C" { }); } \endrst */ - #if defined(PYBIND11_NOEXCEPTIONS) -#define PYBIND11_MODULE(name, variable) \ - static void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &); \ - PYBIND11_PLUGIN_IMPL(name) { \ - if (!pybind11::detail::Py_VersionCheckPassed()) { \ - return nullptr; \ - } \ - auto m = pybind11::module(PYBIND11_TOSTRING(name)); \ - PYBIND11_CONCAT(pybind11_init_, name)(m); \ - return m.ptr(); \ - } \ - void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module & variable) +#define PYBIND11_MODULE(name, variable) \ + static void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &); \ + PYBIND11_PLUGIN_IMPL(name) { \ + PYBIND11_CHECK_PYTHON_VERSION \ + auto m = pybind11::module(PYBIND11_TOSTRING(name)); \ + PYBIND11_CONCAT(pybind11_init_, name)(m); \ + return m.ptr(); \ + } \ + void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &variable) #else -#define PYBIND11_MODULE(name, variable) \ - static void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &); \ - PYBIND11_PLUGIN_IMPL(name) { \ - if (!pybind11::detail::Py_VersionCheckPassed()) { \ - return nullptr; \ - } \ - auto m = pybind11::module(PYBIND11_TOSTRING(name)); \ - GET_PYBIND11_MODULE(pybind11_init_, name, m); \ - } \ - void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module & variable) +#define PYBIND11_MODULE(name, variable) \ + static void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &); \ + PYBIND11_PLUGIN_IMPL(name) { \ + PYBIND11_CHECK_PYTHON_VERSION \ + auto m = pybind11::module(PYBIND11_TOSTRING(name)); \ + try { \ + PYBIND11_CONCAT(pybind11_init_, name)(m); \ + return m.ptr(); \ + } PYBIND11_CATCH_INIT_EXCEPTIONS \ + } \ + void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &variable) #endif @@ -396,23 +405,6 @@ constexpr size_t instance_simple_holder_in_ptrs() { return size_in_ptrs(sizeof(std::shared_ptr)); } -inline bool Py_VersionCheckPassed() { - int major, minor; - if (sscanf(Py_GetVersion(), "%i.%i", &major, &minor) != 2) { - PyErr_SetString(PyExc_ImportError, "Can't parse Python version."); - return false; - } - 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 false; - } - return true; -} - // Forward declarations struct type_info; struct value_and_holder; From 4a3ef83454f5244ea305c7aa1584a2b7fb1c014e Mon Sep 17 00:00:00 2001 From: Amit Patankar Date: Thu, 30 May 2019 14:36:36 -0700 Subject: [PATCH 10/12] Removing unecessary macro. --- include/pybind11/detail/common.h | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/include/pybind11/detail/common.h b/include/pybind11/detail/common.h index 2e57f20d19..8d65cfece3 100644 --- a/include/pybind11/detail/common.h +++ b/include/pybind11/detail/common.h @@ -274,19 +274,6 @@ extern "C" { PyObject *pybind11_init() #endif -// Returns nullptr on an error. -#define GET_PYBIND11_MODULE(pybind11_init_, name, module) \ - try { \ - PYBIND11_CONCAT(pybind11_init_, name)(module); \ - return module.ptr(); \ - } catch (pybind11::error_already_set & e) { \ - PyErr_SetString(PyExc_ImportError, e.what()); \ - return nullptr; \ - } catch (const std::exception &e) { \ - PyErr_SetString(PyExc_ImportError, e.what()); \ - return nullptr; \ - } - /** \rst This macro creates the entry point that will be invoked when the Python interpreter imports an extension module. The module name is given as the fist argument and it From 50d047354bf6b462923952419aabcf2888a41b46 Mon Sep 17 00:00:00 2001 From: Amit Patankar Date: Fri, 7 Jun 2019 11:07:04 -0700 Subject: [PATCH 11/12] Adding a changelog. --- docs/changelog.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/changelog.rst b/docs/changelog.rst index 606be413aa..a221b0978a 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -50,6 +50,9 @@ v2.3.0 (Not yet released) * ``pybind11/stl.h`` does not convert strings to ``vector`` anymore. `#1258 `_. +* Add a ``PYBIND11_NOEXCEPTIONS`` identifier that allows for compilation + without exceptions enabled. + v2.2.4 (September 11, 2018) ----------------------------------------------------- From 6348defb9a00209386e5a205241179150dd1ecb7 Mon Sep 17 00:00:00 2001 From: Amit Patankar Date: Fri, 7 Jun 2019 14:36:32 -0700 Subject: [PATCH 12/12] Add a minor note to the changelog. --- docs/changelog.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index a221b0978a..fb7fe4546f 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -51,7 +51,8 @@ v2.3.0 (Not yet released) `#1258 `_. * Add a ``PYBIND11_NOEXCEPTIONS`` identifier that allows for compilation - without exceptions enabled. + without exceptions enabled. Importing a python module with this identifier + that throws an exception will call ``std::terminate()``. v2.2.4 (September 11, 2018) -----------------------------------------------------