Commit d159a563 by Ralf W. Grosse-Kunstleve Committed by GitHub

static allocation for PyModuleDef, to avoid leak check errors. (#2413)

* 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.

* git rebase master

* moving static PyModuleDef declaration to global scope, as requested by @wjakob

* renaming the two new macros, to start with PYBIND11_DETAIL_MODULE
parent 3c7ef56b
......@@ -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(); \
......
......@@ -862,18 +862,24 @@ public:
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_()");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment