@@ -1255,6 +1255,22 @@ class mod_gil_not_used {
12551255 bool flag_;
12561256};
12571257
1258+ PYBIND11_NAMESPACE_BEGIN (detail)
1259+
1260+ inline bool gil_not_used_option () { return false ; }
1261+ template <typename F, typename ... O>
1262+ bool gil_not_used_option (F &&, O &&...o );
1263+ template <typename ... O>
1264+ inline bool gil_not_used_option (mod_gil_not_used f, O &&...o ) {
1265+ return f.flag () || gil_not_used_option (o...);
1266+ }
1267+ template <typename F, typename ... O>
1268+ inline bool gil_not_used_option (F &&, O &&...o ) {
1269+ return false || gil_not_used_option (o...);
1270+ }
1271+
1272+ PYBIND11_NAMESPACE_END (detail)
1273+
12581274// / Wrapper for Python extension modules
12591275class module_ : public object {
12601276public:
@@ -1389,6 +1405,63 @@ class module_ : public object {
13891405 // For Python 2, reinterpret_borrow was correct.
13901406 return reinterpret_borrow<module_>(m);
13911407 }
1408+
1409+ /* * \rst
1410+ Initialized a module def for use with multi-phase module initialization.
1411+
1412+ ``def`` should point to a statically allocated module_def.
1413+ ``slots`` must point to an initialized array of slots with space for at
1414+ least one additional slot to be populated based on the options.
1415+ \endrst */
1416+ template <typename ... Options>
1417+ static object init_module_def (const char *name,
1418+ const char *doc,
1419+ module_def *def,
1420+ PyModuleDef_Slot *slots,
1421+ Options &&...options) {
1422+ int i = 0 ;
1423+ while (slots[i].slot != 0 ) {
1424+ ++i;
1425+ }
1426+
1427+ bool nogil PYBIND11_MAYBE_UNUSED = detail::gil_not_used_option (options...);
1428+
1429+ if (nogil) {
1430+ #ifdef Py_mod_gil
1431+ slots[i].slot = Py_mod_gil;
1432+ # ifdef Py_GIL_DISABLED
1433+ slots[i].value = Py_MOD_GIL_NOT_USED;
1434+ # else
1435+ slots[i].value = Py_MOD_GIL_USED;
1436+ # endif
1437+ ++i;
1438+ #endif
1439+ }
1440+
1441+ slots[i].slot = 0 ;
1442+ slots[i].value = nullptr ;
1443+
1444+ // module_def is PyModuleDef
1445+ // Placement new (not an allocation).
1446+ def = new (def)
1447+ PyModuleDef{/* m_base */ PyModuleDef_HEAD_INIT,
1448+ /* m_name */ name,
1449+ /* m_doc */ options::show_user_defined_docstrings () ? doc : nullptr ,
1450+ /* m_size */ 0 ,
1451+ /* m_methods */ nullptr ,
1452+ /* m_slots */ slots,
1453+ /* m_traverse */ nullptr ,
1454+ /* m_clear */ nullptr ,
1455+ /* m_free */ nullptr };
1456+ auto *m = PyModuleDef_Init (def);
1457+ if (m == nullptr ) {
1458+ if (PyErr_Occurred ()) {
1459+ throw error_already_set ();
1460+ }
1461+ pybind11_fail (" Internal error in module_::init_module_def()" );
1462+ }
1463+ return reinterpret_borrow<object>(m);
1464+ }
13921465};
13931466
13941467PYBIND11_NAMESPACE_BEGIN (detail)
0 commit comments