Skip to content

Commit fafd9b4

Browse files
committed
static allocation for PyModuleDef, to portably avoid leak check errors.
This PR solves the same issue as pybind#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 41aa926 commit fafd9b4

2 files changed

Lines changed: 15 additions & 7 deletions

File tree

include/pybind11/detail/common.h

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

include/pybind11/pybind11.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -857,18 +857,18 @@ class module : public object {
857857
PYBIND11_OBJECT_DEFAULT(module, object, PyModule_Check)
858858

859859
/// Create a new top-level Python module with the given name and docstring
860-
explicit module(const char *name, const char *doc = nullptr) {
861-
if (!options::show_user_defined_docstrings()) doc = nullptr;
862-
#if PY_MAJOR_VERSION >= 3
863-
auto *def = new PyModuleDef();
860+
explicit module(const char *name, const char *doc = nullptr, PyModuleDef *def = nullptr) {
861+
if (!def) def = new PyModuleDef();
864862
std::memset(def, 0, sizeof(PyModuleDef));
865863
def->m_name = name;
866-
def->m_doc = doc;
864+
def->m_doc = options::show_user_defined_docstrings() ? doc : nullptr;
867865
def->m_size = -1;
868866
Py_INCREF(def);
869867
m_ptr = PyModule_Create(def);
870868
#else
871-
m_ptr = Py_InitModule3(name, nullptr, doc);
869+
explicit module(const char *name, const char *doc = nullptr) {
870+
m_ptr = Py_InitModule3(
871+
name, nullptr, options::show_user_defined_docstrings() ? doc : nullptr);
872872
#endif
873873
if (m_ptr == nullptr)
874874
pybind11_fail("Internal error in module::module()");

0 commit comments

Comments
 (0)