Skip to content

Commit 07b069a

Browse files
Unify Python 2 & 3 py::module constructor, and make contructor with pre-allocated PyModuleDef private (#2534)
1 parent 6d2d08d commit 07b069a

2 files changed

Lines changed: 45 additions & 17 deletions

File tree

include/pybind11/detail/common.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ extern "C" {
311311
#define PYBIND11_DETAIL_MODULE_STATIC_DEF(name) \
312312
static PyModuleDef PYBIND11_CONCAT(pybind11_module_def_, name);
313313
#define PYBIND11_DETAIL_MODULE_CREATE(name) \
314-
auto m = pybind11::module( \
314+
auto m = pybind11::detail::create_top_level_module( \
315315
PYBIND11_TOSTRING(name), nullptr, \
316316
&PYBIND11_CONCAT(pybind11_module_def_, name));
317317
#else

include/pybind11/pybind11.h

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -856,35 +856,32 @@ class cpp_function : public function {
856856
}
857857
};
858858

859+
860+
#if PY_MAJOR_VERSION >= 3
861+
class module_;
862+
863+
PYBIND11_NAMESPACE_BEGIN(detail)
864+
inline module_ create_top_level_module(const char *name, const char *doc, PyModuleDef *def);
865+
PYBIND11_NAMESPACE_END(detail)
866+
#endif
867+
859868
/// Wrapper for Python extension modules
860869
class module_ : public object {
861870
public:
862871
PYBIND11_OBJECT_DEFAULT(module_, object, PyModule_Check)
863872

864873
/// Create a new top-level Python module with the given name and docstring
874+
explicit module_(const char *name, const char *doc = nullptr)
865875
#if PY_MAJOR_VERSION >= 3
866-
explicit module_(const char *name, const char *doc = nullptr, PyModuleDef *def = nullptr) {
867-
if (!def) def = new PyModuleDef();
868-
def = new (def) PyModuleDef { // Placement new (not an allocation).
869-
/* m_base */ PyModuleDef_HEAD_INIT,
870-
/* m_name */ name,
871-
/* m_doc */ options::show_user_defined_docstrings() ? doc : nullptr,
872-
/* m_size */ -1,
873-
/* m_methods */ nullptr,
874-
/* m_slots */ nullptr,
875-
/* m_traverse */ nullptr,
876-
/* m_clear */ nullptr,
877-
/* m_free */ nullptr
878-
};
879-
m_ptr = PyModule_Create(def);
876+
: module_(name, doc, new PyModuleDef()) {}
880877
#else
881-
explicit module_(const char *name, const char *doc = nullptr) {
878+
{
882879
m_ptr = Py_InitModule3(name, nullptr, options::show_user_defined_docstrings() ? doc : nullptr);
883-
#endif
884880
if (m_ptr == nullptr)
885881
pybind11_fail("Internal error in module_::module_()");
886882
inc_ref();
887883
}
884+
#endif
888885

889886
/** \rst
890887
Create Python binding for a new function within the module scope. ``Func``
@@ -949,10 +946,41 @@ class module_ : public object {
949946

950947
PyModule_AddObject(ptr(), name, obj.inc_ref().ptr() /* steals a reference */);
951948
}
949+
950+
private:
951+
#if PY_MAJOR_VERSION >= 3
952+
friend module_ detail::create_top_level_module(const char *, const char *, PyModuleDef *);
953+
954+
explicit module_(const char *name, const char *doc, PyModuleDef *def) {
955+
def = new (def) PyModuleDef { // Placement new (not an allocation).
956+
/* m_base */ PyModuleDef_HEAD_INIT,
957+
/* m_name */ name,
958+
/* m_doc */ options::show_user_defined_docstrings() ? doc : nullptr,
959+
/* m_size */ -1,
960+
/* m_methods */ nullptr,
961+
/* m_slots */ nullptr,
962+
/* m_traverse */ nullptr,
963+
/* m_clear */ nullptr,
964+
/* m_free */ nullptr
965+
};
966+
m_ptr = PyModule_Create(def);
967+
if (m_ptr == nullptr)
968+
pybind11_fail("Internal error in module::module()");
969+
inc_ref();
970+
}
971+
#endif
952972
};
953973

954974
using module = module_;
955975

976+
#if PY_MAJOR_VERSION >= 3
977+
PYBIND11_NAMESPACE_BEGIN(detail)
978+
inline module_ create_top_level_module(const char *name, const char *doc, PyModuleDef *def) {
979+
return module_(name, doc, def);
980+
}
981+
PYBIND11_NAMESPACE_END(detail)
982+
#endif
983+
956984
/// \ingroup python_builtins
957985
/// Return a dictionary representing the global variables in the current execution frame,
958986
/// or ``__main__.__dict__`` if there is no frame (usually when the interpreter is embedded).

0 commit comments

Comments
 (0)