Skip to content

Commit 0d0b37c

Browse files
committed
static allocation for PyModuleDef, to portably avoid leak check errors.
This PR solves the same issue as #2019 (rolled back), but in a way that is certain to be portable and will work for any leak checker. The Python 3 documentation suggests `static` allocation for `PyModuleDef`: * https://docs.python.org/3/c-api/module.html#initializing-c-modules * The module definition struct, which holds all information needed to create a module object. There is usually only one statically initialized variable of this type for each module. This PR changes the `PYBIND11_MODULE` macro accordingly: `static PyModuleDef mdef;` The `pybind11::module::module` code is slightly refactored, with the idea to make the future removal of Python 2 support straightforward.
1 parent 3c061f2 commit 0d0b37c

File tree

2 files changed

+15
-6
lines changed

2 files changed

+15
-6
lines changed

include/pybind11/detail/common.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,13 +306,21 @@ extern "C" {
306306
});
307307
}
308308
\endrst */
309+
#if PY_MAJOR_VERSION >= 3
310+
#define PYBIND11_MODULE_PY2_VS_PY3_SPECIFIC(name) \
311+
static PyModuleDef mdef; \
312+
auto m = pybind11::module(PYBIND11_TOSTRING(name), nullptr, &mdef);
313+
#else
314+
#define PYBIND11_MODULE_PY2_VS_PY3_SPECIFIC(name) \
315+
auto m = pybind11::module(PYBIND11_TOSTRING(name));
316+
#endif
309317
#define PYBIND11_MODULE(name, variable) \
310318
PYBIND11_MAYBE_UNUSED \
311319
static void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &); \
312320
PYBIND11_PLUGIN_IMPL(name) { \
313321
PYBIND11_CHECK_PYTHON_VERSION \
314322
PYBIND11_ENSURE_INTERNALS_READY \
315-
auto m = pybind11::module(PYBIND11_TOSTRING(name)); \
323+
PYBIND11_MODULE_PY2_VS_PY3_SPECIFIC(name) \
316324
try { \
317325
PYBIND11_CONCAT(pybind11_init_, name)(m); \
318326
return m.ptr(); \

include/pybind11/pybind11.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -827,18 +827,19 @@ class module : public object {
827827
PYBIND11_OBJECT_DEFAULT(module, object, PyModule_Check)
828828

829829
/// Create a new top-level Python module with the given name and docstring
830-
explicit module(const char *name, const char *doc = nullptr) {
831-
if (!options::show_user_defined_docstrings()) doc = nullptr;
832830
#if PY_MAJOR_VERSION >= 3
833-
PyModuleDef *def = new PyModuleDef();
831+
explicit module(const char *name, const char *doc = nullptr, PyModuleDef *def = nullptr) {
832+
if (!def) def = new PyModuleDef();
834833
std::memset(def, 0, sizeof(PyModuleDef));
835834
def->m_name = name;
836-
def->m_doc = doc;
835+
def->m_doc = options::show_user_defined_docstrings() ? doc : nullptr;
837836
def->m_size = -1;
838837
Py_INCREF(def);
839838
m_ptr = PyModule_Create(def);
840839
#else
841-
m_ptr = Py_InitModule3(name, nullptr, doc);
840+
explicit module(const char *name, const char *doc = nullptr) {
841+
m_ptr = Py_InitModule3(
842+
name, nullptr, options::show_user_defined_docstrings() ? doc : nullptr);
842843
#endif
843844
if (m_ptr == nullptr)
844845
pybind11_fail("Internal error in module::module()");

0 commit comments

Comments
 (0)