@@ -1325,6 +1325,38 @@ inline void *multi_interp_slot(F &&, O &&...o) {
13251325}
13261326#endif
13271327
1328+ // / Must be a POD type, and must hold enough entries for all of the possible slots PLUS ONE for
1329+ // / the sentinel (0) end slot.
1330+ using slots_array = std::array<PyModuleDef_Slot, 4 >;
1331+
1332+ // / Initialize an array of slots based on the supplied exec slot and options.
1333+ template <typename ... Options>
1334+ static slots_array init_slots (int (*exec_fn)(PyObject *), Options &&...options ) noexcept {
1335+ /* NOTE: slots_array MUST be large enough to hold all possible options. If you add an option
1336+ here, you MUST also increase the size of slots_array in the type alias above! */
1337+ slots_array slots;
1338+ size_t next_slot = 0 ;
1339+
1340+ if (exec_fn != nullptr ) {
1341+ slots[next_slot++] = {Py_mod_exec, reinterpret_cast <void *>(exec_fn)};
1342+ }
1343+
1344+ #ifdef Py_mod_multiple_interpreters
1345+ slots[next_slot++] = {Py_mod_multiple_interpreters, multi_interp_slot (options...)};
1346+ #endif
1347+
1348+ if (gil_not_used_option (options...)) {
1349+ #if defined(Py_mod_gil) && defined(Py_GIL_DISABLED)
1350+ slots[next_slot++] = {Py_mod_gil, Py_MOD_GIL_NOT_USED};
1351+ #endif
1352+ }
1353+
1354+ // slots must have a zero end sentinel
1355+ slots[next_slot++] = {0 , nullptr };
1356+
1357+ return slots;
1358+ }
1359+
13281360PYBIND11_NAMESPACE_END (detail)
13291361
13301362// / Wrapper for Python extension modules
@@ -1438,19 +1470,19 @@ class module_ : public object {
14381470 PyModule_AddObject (ptr (), name, obj.inc_ref ().ptr () /* steals a reference */ );
14391471 }
14401472
1441- using module_def = PyModuleDef; // TODO: Can this be removed (it was needed only for Python 2)?
1473+ // DEPRECATED (since PR #5688): Use PyModuleDef directly instead.
1474+ using module_def = PyModuleDef;
14421475
14431476 /* * \rst
14441477 Create a new top-level module that can be used as the main module of a C extension.
14451478
1446- ``def`` should point to a statically allocated module_def .
1479+ ``def`` should point to a statically allocated PyModuleDef .
14471480 \endrst */
14481481 static module_ create_extension_module (const char *name,
14491482 const char *doc,
1450- module_def *def,
1483+ PyModuleDef *def,
14511484 mod_gil_not_used gil_not_used
14521485 = mod_gil_not_used(false )) {
1453- // module_def is PyModuleDef
14541486 // Placement new (not an allocation).
14551487 new (def) PyModuleDef{/* m_base */ PyModuleDef_HEAD_INIT,
14561488 /* m_name */ name,
@@ -1478,74 +1510,6 @@ class module_ : public object {
14781510 // For Python 2, reinterpret_borrow was correct.
14791511 return reinterpret_borrow<module_>(m);
14801512 }
1481-
1482- // / Must be a POD type, and must hold enough entries for all of the possible slots PLUS ONE for
1483- // / the sentinel (0) end slot.
1484- using slots_array = std::array<PyModuleDef_Slot, 4 >;
1485-
1486- /* * \rst
1487- Initialize a module def for use with multi-phase module initialization.
1488-
1489- ``def`` should point to a statically allocated module_def.
1490- ``slots`` must already contain a Py_mod_exec or Py_mod_create slot and will be filled with
1491- additional slots from the supplied options (and the empty sentinel slot).
1492- \endrst */
1493- template <typename ... Options>
1494- static object initialize_multiphase_module_def (const char *name,
1495- const char *doc,
1496- module_def *def,
1497- slots_array &slots,
1498- Options &&...options) {
1499- size_t next_slot = 0 ;
1500- size_t term_slot = slots.size () - 1 ;
1501-
1502- // find the end of the supplied slots
1503- while (next_slot < term_slot && slots[next_slot].slot != 0 ) {
1504- ++next_slot;
1505- }
1506-
1507- #ifdef Py_mod_multiple_interpreters
1508- if (next_slot >= term_slot) {
1509- pybind11_fail (" initialize_multiphase_module_def: not enough space in slots" );
1510- }
1511- slots[next_slot++] = {Py_mod_multiple_interpreters, detail::multi_interp_slot (options...)};
1512- #endif
1513-
1514- if (detail::gil_not_used_option (options...)) {
1515- #if defined(Py_mod_gil) && defined(Py_GIL_DISABLED)
1516- if (next_slot >= term_slot) {
1517- pybind11_fail (" initialize_multiphase_module_def: not enough space in slots" );
1518- }
1519- slots[next_slot++] = {Py_mod_gil, Py_MOD_GIL_NOT_USED};
1520- #endif
1521- }
1522-
1523- // slots must have a zero end sentinel
1524- if (next_slot > term_slot) {
1525- pybind11_fail (" initialize_multiphase_module_def: not enough space in slots" );
1526- }
1527- slots[next_slot++] = {0 , nullptr };
1528-
1529- // module_def is PyModuleDef
1530- // Placement new (not an allocation).
1531- new (def) PyModuleDef{/* m_base */ PyModuleDef_HEAD_INIT,
1532- /* m_name */ name,
1533- /* m_doc */ options::show_user_defined_docstrings () ? doc : nullptr ,
1534- /* m_size */ 0 ,
1535- /* m_methods */ nullptr ,
1536- /* m_slots */ &slots[0 ],
1537- /* m_traverse */ nullptr ,
1538- /* m_clear */ nullptr ,
1539- /* m_free */ nullptr };
1540- auto *m = PyModuleDef_Init (def);
1541- if (m == nullptr ) {
1542- if (PyErr_Occurred ()) {
1543- throw error_already_set ();
1544- }
1545- pybind11_fail (" Internal error in module_::initialize_multiphase_module_def()" );
1546- }
1547- return reinterpret_borrow<object>(m);
1548- }
15491513};
15501514
15511515PYBIND11_NAMESPACE_BEGIN (detail)
0 commit comments