From 1f41e723178fb11ed215beee427343681dd225c8 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 31 Aug 2020 12:14:05 -0700 Subject: [PATCH 1/4] Initializing PyModuleDef object with PyModuleDef_HEAD_INIT. Python 3.8 documentation: m_base - Always initialize this member to PyModuleDef_HEAD_INIT. Long-standing (since first github commit in 2015), inconsequential bug. Also removing inconsequential Py_INCREF(def): PyModule_Create() resets the reference count to 1. --- include/pybind11/detail/common.h | 10 +++++++++- include/pybind11/pybind11.h | 24 +++++++++++++++--------- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/include/pybind11/detail/common.h b/include/pybind11/detail/common.h index 1f8390fbab..217a34f740 100644 --- a/include/pybind11/detail/common.h +++ b/include/pybind11/detail/common.h @@ -307,13 +307,21 @@ extern "C" { }); } \endrst */ +#if PY_MAJOR_VERSION >= 3 +#define PYBIND11_MODULE_DETAIL_CREATE(name) \ + static PyModuleDef mdef; \ + auto m = pybind11::module(PYBIND11_TOSTRING(name), nullptr, &mdef); +#else +#define PYBIND11_MODULE_DETAIL_CREATE(name) \ + auto m = pybind11::module(PYBIND11_TOSTRING(name)); +#endif #define PYBIND11_MODULE(name, variable) \ PYBIND11_MAYBE_UNUSED \ static void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &); \ PYBIND11_PLUGIN_IMPL(name) { \ PYBIND11_CHECK_PYTHON_VERSION \ PYBIND11_ENSURE_INTERNALS_READY \ - auto m = pybind11::module(PYBIND11_TOSTRING(name)); \ + PYBIND11_MODULE_DETAIL_CREATE(name) \ try { \ PYBIND11_CONCAT(pybind11_init_, name)(m); \ return m.ptr(); \ diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index da3a78c250..f45e959a9d 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -862,18 +862,24 @@ class module_ : public object { PYBIND11_OBJECT_DEFAULT(module_, object, PyModule_Check) /// Create a new top-level Python module with the given name and docstring - explicit module_(const char *name, const char *doc = nullptr) { - if (!options::show_user_defined_docstrings()) doc = nullptr; #if PY_MAJOR_VERSION >= 3 - auto *def = new PyModuleDef(); - std::memset(def, 0, sizeof(PyModuleDef)); - def->m_name = name; - def->m_doc = doc; - def->m_size = -1; - Py_INCREF(def); + explicit module(const char *name, const char *doc = nullptr, PyModuleDef *def = nullptr) { + if (!def) def = new PyModuleDef(); + def = new (def) PyModuleDef { // Placement new (not an allocation). + /* m_base */ PyModuleDef_HEAD_INIT, + /* m_name */ name, + /* m_doc */ options::show_user_defined_docstrings() ? doc : nullptr, + /* m_size */ -1, + /* m_methods */ nullptr, + /* m_slots */ nullptr, + /* m_traverse */ nullptr, + /* m_clear */ nullptr, + /* m_free */ nullptr + }; m_ptr = PyModule_Create(def); #else - m_ptr = Py_InitModule3(name, nullptr, doc); + explicit module_(const char *name, const char *doc = nullptr) { + m_ptr = Py_InitModule3(name, nullptr, options::show_user_defined_docstrings() ? doc : nullptr); #endif if (m_ptr == nullptr) pybind11_fail("Internal error in module_::module_()"); From 68524f5495f426f6f64afbe37c068929606617d1 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Wed, 16 Sep 2020 16:01:39 -0700 Subject: [PATCH 2/4] git rebase master --- include/pybind11/pybind11.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index f45e959a9d..0cde4fa955 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -863,7 +863,7 @@ class module_ : public object { /// Create a new top-level Python module with the given name and docstring #if PY_MAJOR_VERSION >= 3 - explicit module(const char *name, const char *doc = nullptr, PyModuleDef *def = nullptr) { + explicit module_(const char *name, const char *doc = nullptr, PyModuleDef *def = nullptr) { if (!def) def = new PyModuleDef(); def = new (def) PyModuleDef { // Placement new (not an allocation). /* m_base */ PyModuleDef_HEAD_INIT, From 62bfaf86b36293bc2073c2900c941fbccc41b22e Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Fri, 25 Sep 2020 13:39:11 -0700 Subject: [PATCH 3/4] moving static PyModuleDef declaration to global scope, as requested by @wjakob --- include/pybind11/detail/common.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/include/pybind11/detail/common.h b/include/pybind11/detail/common.h index 217a34f740..2f3ab84059 100644 --- a/include/pybind11/detail/common.h +++ b/include/pybind11/detail/common.h @@ -308,14 +308,19 @@ extern "C" { } \endrst */ #if PY_MAJOR_VERSION >= 3 +#define PYBIND11_MODULE_DETAIL_STATIC_DEF(name) \ + static PyModuleDef PYBIND11_CONCAT(pybind11_module_def_, name); #define PYBIND11_MODULE_DETAIL_CREATE(name) \ - static PyModuleDef mdef; \ - auto m = pybind11::module(PYBIND11_TOSTRING(name), nullptr, &mdef); + auto m = pybind11::module( \ + PYBIND11_TOSTRING(name), nullptr, \ + &PYBIND11_CONCAT(pybind11_module_def_, name)); #else +#define PYBIND11_MODULE_DETAIL_STATIC_DEF(name) #define PYBIND11_MODULE_DETAIL_CREATE(name) \ auto m = pybind11::module(PYBIND11_TOSTRING(name)); #endif #define PYBIND11_MODULE(name, variable) \ + PYBIND11_MODULE_DETAIL_STATIC_DEF(name) \ PYBIND11_MAYBE_UNUSED \ static void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &); \ PYBIND11_PLUGIN_IMPL(name) { \ From d787c24d669f7164061ed82f293365104aa81323 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sat, 26 Sep 2020 21:46:36 -0700 Subject: [PATCH 4/4] renaming the two new macros, to start with PYBIND11_DETAIL_MODULE --- include/pybind11/detail/common.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/pybind11/detail/common.h b/include/pybind11/detail/common.h index 2f3ab84059..c18970ddd1 100644 --- a/include/pybind11/detail/common.h +++ b/include/pybind11/detail/common.h @@ -308,25 +308,25 @@ extern "C" { } \endrst */ #if PY_MAJOR_VERSION >= 3 -#define PYBIND11_MODULE_DETAIL_STATIC_DEF(name) \ +#define PYBIND11_DETAIL_MODULE_STATIC_DEF(name) \ static PyModuleDef PYBIND11_CONCAT(pybind11_module_def_, name); -#define PYBIND11_MODULE_DETAIL_CREATE(name) \ +#define PYBIND11_DETAIL_MODULE_CREATE(name) \ auto m = pybind11::module( \ PYBIND11_TOSTRING(name), nullptr, \ &PYBIND11_CONCAT(pybind11_module_def_, name)); #else -#define PYBIND11_MODULE_DETAIL_STATIC_DEF(name) -#define PYBIND11_MODULE_DETAIL_CREATE(name) \ +#define PYBIND11_DETAIL_MODULE_STATIC_DEF(name) +#define PYBIND11_DETAIL_MODULE_CREATE(name) \ auto m = pybind11::module(PYBIND11_TOSTRING(name)); #endif #define PYBIND11_MODULE(name, variable) \ - PYBIND11_MODULE_DETAIL_STATIC_DEF(name) \ + PYBIND11_DETAIL_MODULE_STATIC_DEF(name) \ PYBIND11_MAYBE_UNUSED \ static void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &); \ PYBIND11_PLUGIN_IMPL(name) { \ PYBIND11_CHECK_PYTHON_VERSION \ PYBIND11_ENSURE_INTERNALS_READY \ - PYBIND11_MODULE_DETAIL_CREATE(name) \ + PYBIND11_DETAIL_MODULE_CREATE(name) \ try { \ PYBIND11_CONCAT(pybind11_init_, name)(m); \ return m.ptr(); \