diff --git a/include/pybind11/detail/common.h b/include/pybind11/detail/common.h index 1f8390fbab..c18970ddd1 100644 --- a/include/pybind11/detail/common.h +++ b/include/pybind11/detail/common.h @@ -307,13 +307,26 @@ extern "C" { }); } \endrst */ +#if PY_MAJOR_VERSION >= 3 +#define PYBIND11_DETAIL_MODULE_STATIC_DEF(name) \ + static PyModuleDef PYBIND11_CONCAT(pybind11_module_def_, name); +#define PYBIND11_DETAIL_MODULE_CREATE(name) \ + auto m = pybind11::module( \ + PYBIND11_TOSTRING(name), nullptr, \ + &PYBIND11_CONCAT(pybind11_module_def_, name)); +#else +#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_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 \ - auto m = pybind11::module(PYBIND11_TOSTRING(name)); \ + PYBIND11_DETAIL_MODULE_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..0cde4fa955 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_()");