Skip to content

Commit a65a38b

Browse files
committed
Move detail::create_top_level_module to module_::create_extension_module, and unify Python 2 and 3 signature again
1 parent 7e51331 commit a65a38b

File tree

4 files changed

+55
-65
lines changed

4 files changed

+55
-65
lines changed

include/pybind11/detail/common.h

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -261,20 +261,6 @@ extern "C" {
261261
return nullptr; \
262262
} \
263263

264-
#if PY_MAJOR_VERSION >= 3
265-
#define PYBIND11_DETAIL_MODULE_STATIC_DEF(name) \
266-
static PyModuleDef PYBIND11_CONCAT(pybind11_module_def_, name);
267-
#define PYBIND11_DETAIL_MODULE_CREATE(name) \
268-
auto m = ::pybind11::detail::create_top_level_module( \
269-
PYBIND11_TOSTRING(name), nullptr, \
270-
&PYBIND11_CONCAT(pybind11_module_def_, name));
271-
#else
272-
#define PYBIND11_DETAIL_MODULE_STATIC_DEF(name)
273-
#define PYBIND11_DETAIL_MODULE_CREATE(name) \
274-
auto m = ::pybind11::detail::create_top_level_module( \
275-
PYBIND11_TOSTRING(name), nullptr);
276-
#endif
277-
278264
/** \rst
279265
***Deprecated in favor of PYBIND11_MODULE***
280266
@@ -324,13 +310,16 @@ extern "C" {
324310
}
325311
\endrst */
326312
#define PYBIND11_MODULE(name, variable) \
327-
PYBIND11_DETAIL_MODULE_STATIC_DEF(name) \
313+
static ::pybind11::module_::module_def \
314+
PYBIND11_CONCAT(pybind11_module_def_, name); \
328315
PYBIND11_MAYBE_UNUSED \
329316
static void PYBIND11_CONCAT(pybind11_init_, name)(::pybind11::module_ &); \
330317
PYBIND11_PLUGIN_IMPL(name) { \
331318
PYBIND11_CHECK_PYTHON_VERSION \
332319
PYBIND11_ENSURE_INTERNALS_READY \
333-
PYBIND11_DETAIL_MODULE_CREATE(name) \
320+
auto m = ::pybind11::module_::create_extension_module( \
321+
PYBIND11_TOSTRING(name), nullptr, \
322+
&PYBIND11_CONCAT(pybind11_module_def_, name)); \
334323
try { \
335324
PYBIND11_CONCAT(pybind11_init_, name)(m); \
336325
return m.ptr(); \

include/pybind11/embed.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,13 @@
4646
}
4747
\endrst */
4848
#define PYBIND11_EMBEDDED_MODULE(name, variable) \
49-
PYBIND11_DETAIL_MODULE_STATIC_DEF(name) \
49+
static ::pybind11::module_::module_def \
50+
PYBIND11_CONCAT(pybind11_module_def_, name); \
5051
static void PYBIND11_CONCAT(pybind11_init_, name)(::pybind11::module_ &); \
5152
static PyObject PYBIND11_CONCAT(*pybind11_init_wrapper_, name)() { \
52-
PYBIND11_DETAIL_MODULE_CREATE(name) \
53+
auto m = ::pybind11::module_::create_extension_module( \
54+
PYBIND11_TOSTRING(name), nullptr, \
55+
&PYBIND11_CONCAT(pybind11_module_def_, name)); \
5356
try { \
5457
PYBIND11_CONCAT(pybind11_init_, name)(m); \
5558
return m.ptr(); \

include/pybind11/pybind11.h

Lines changed: 43 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -868,16 +868,6 @@ class cpp_function : public function {
868868
}
869869
};
870870

871-
class module_;
872-
873-
PYBIND11_NAMESPACE_BEGIN(detail)
874-
#if PY_MAJOR_VERSION >= 3
875-
inline module_ create_top_level_module(const char *name, const char *doc, PyModuleDef *def);
876-
#else
877-
inline module_ create_top_level_module(const char *name, const char *doc);
878-
#endif
879-
PYBIND11_NAMESPACE_END(detail)
880-
881871
/// Wrapper for Python extension modules
882872
class module_ : public object {
883873
public:
@@ -887,9 +877,9 @@ class module_ : public object {
887877
PYBIND11_DEPRECATED("Use PYBIND11_MODULE, module_::def_submodule, or module_::import instead")
888878
explicit module_(const char *name, const char *doc = nullptr) {
889879
#if PY_MAJOR_VERSION >= 3
890-
*this = detail::create_top_level_module(name, doc, new PyModuleDef());
880+
*this = create_extension_module(name, doc, new PyModuleDef());
891881
#else
892-
*this = detail::create_top_level_module(name, doc);
882+
*this = create_extension_module(name, doc, nullptr);
893883
#endif
894884
}
895885

@@ -958,43 +948,54 @@ class module_ : public object {
958948

959949
PyModule_AddObject(ptr(), name, obj.inc_ref().ptr() /* steals a reference */);
960950
}
951+
952+
#if PY_MAJOR_VERSION >= 3
953+
using module_def = PyModuleDef;
954+
#else
955+
struct module_def {};
956+
#endif
957+
958+
/** \rst
959+
Create a new top-level module that can be used as the main module of a C extension.
960+
961+
For Python 3, ``def`` should point to a staticly allocated module_def.
962+
For Python 2, ``def`` can be a nullptr and is completely ignored.
963+
\endrst */
964+
static module_ create_extension_module(const char *name, const char *doc, module_def *def) {
965+
#if PY_MAJOR_VERSION >= 3
966+
// module_def is PyModuleDef
967+
def = new (def) PyModuleDef { // Placement new (not an allocation).
968+
/* m_base */ PyModuleDef_HEAD_INIT,
969+
/* m_name */ name,
970+
/* m_doc */ options::show_user_defined_docstrings() ? doc : nullptr,
971+
/* m_size */ -1,
972+
/* m_methods */ nullptr,
973+
/* m_slots */ nullptr,
974+
/* m_traverse */ nullptr,
975+
/* m_clear */ nullptr,
976+
/* m_free */ nullptr
977+
};
978+
auto m = PyModule_Create(def);
979+
if (m == nullptr)
980+
pybind11_fail("Internal error in module_::create_extension_module()");
981+
// TODO: Should be reinterpret_steal, but Python also steals it again when returned from PyInit_...
982+
return reinterpret_borrow<module_>(m);
983+
#else
984+
// Ignore module_def *def; only necessary for Python 3
985+
(void) def;
986+
auto m = Py_InitModule3(name, nullptr, options::show_user_defined_docstrings() ? doc : nullptr);
987+
if (m == nullptr)
988+
pybind11_fail("Internal error in module_::create_extension_module()");
989+
return reinterpret_borrow<module_>(m);
990+
#endif
991+
}
961992
};
962993

963994
// When inside a namespace (or anywhere as long as it's not the first item on a line),
964995
// C++20 allows "module" to be used. This is provided for backward compatibility, and for
965996
// simplicity, if someone wants to use py::module for example, that is perfectly safe.
966997
using module = module_;
967998

968-
PYBIND11_NAMESPACE_BEGIN(detail)
969-
#if PY_MAJOR_VERSION >= 3
970-
inline module_ create_top_level_module(const char *name, const char *doc, PyModuleDef *def) {
971-
def = new (def) PyModuleDef { // Placement new (not an allocation).
972-
/* m_base */ PyModuleDef_HEAD_INIT,
973-
/* m_name */ name,
974-
/* m_doc */ options::show_user_defined_docstrings() ? doc : nullptr,
975-
/* m_size */ -1,
976-
/* m_methods */ nullptr,
977-
/* m_slots */ nullptr,
978-
/* m_traverse */ nullptr,
979-
/* m_clear */ nullptr,
980-
/* m_free */ nullptr
981-
};
982-
auto m = PyModule_Create(def);
983-
if (m == nullptr)
984-
pybind11_fail("Internal error in detail::create_top_level_module()");
985-
// TODO: Should be reinterpret_steal, but Python also steals it again when returned from PyInit_...
986-
return reinterpret_borrow<module_>(m);
987-
}
988-
#else
989-
inline module_ create_top_level_module(const char *name, const char *doc) {
990-
auto m = Py_InitModule3(name, nullptr, options::show_user_defined_docstrings() ? doc : nullptr);
991-
if (m == nullptr)
992-
pybind11_fail("Internal error in detail::create_top_level_module()");
993-
return reinterpret_borrow<module_>(m);
994-
}
995-
#endif
996-
PYBIND11_NAMESPACE_END(detail)
997-
998999
/// \ingroup python_builtins
9991000
/// Return a dictionary representing the global variables in the current execution frame,
10001001
/// or ``__main__.__dict__`` if there is no frame (usually when the interpreter is embedded).

tests/test_modules.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,8 @@ TEST_SUBMODULE(modules, m) {
6262
class Dupe3 { };
6363
class DupeException { };
6464

65-
#if PY_MAJOR_VERSION >= 3
66-
auto dm = py::detail::create_top_level_module("dummy", nullptr, new PyModuleDef);
67-
#else
68-
auto dm = py::detail::create_top_level_module("dummy", nullptr);
69-
#endif
65+
// Go ahead and leak, until we have a non-leaking py::module_ constructor
66+
auto dm = py::module_::create_extension_module("dummy", nullptr, new py::module_::module_def);
7067
auto failures = py::list();
7168

7269
py::class_<Dupe1>(dm, "Dupe1");

0 commit comments

Comments
 (0)