@@ -1255,6 +1255,22 @@ class mod_gil_not_used {
1255
1255
bool flag_;
1256
1256
};
1257
1257
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 gil_not_used_option (o...);
1270
+ }
1271
+
1272
+ PYBIND11_NAMESPACE_END (detail)
1273
+
1258
1274
// / Wrapper for Python extension modules
1259
1275
class module_ : public object {
1260
1276
public:
@@ -1389,6 +1405,61 @@ class module_ : public object {
1389
1405
// For Python 2, reinterpret_borrow was correct.
1390
1406
return reinterpret_borrow<module_>(m);
1391
1407
}
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 initialize_multiphase_module_def (const char *name,
1418
+ const char *doc,
1419
+ module_def *def,
1420
+ PyModuleDef_Slot *slots,
1421
+ Options &&...options) {
1422
+ int next_slot = 0 ;
1423
+ while (slots[next_slot].slot != 0 ) {
1424
+ ++next_slot;
1425
+ }
1426
+
1427
+ bool nogil PYBIND11_MAYBE_UNUSED = detail::gil_not_used_option (options...);
1428
+ if (nogil) {
1429
+ #ifdef Py_mod_gil
1430
+ slots[next_slot].slot = Py_mod_gil;
1431
+ # ifdef Py_GIL_DISABLED
1432
+ slots[next_slot].value = Py_MOD_GIL_NOT_USED;
1433
+ # else
1434
+ slots[next_slot].value = Py_MOD_GIL_USED;
1435
+ # endif
1436
+ ++next_slot;
1437
+ #endif
1438
+ }
1439
+
1440
+ slots[next_slot] = {0 , nullptr };
1441
+
1442
+ // module_def is PyModuleDef
1443
+ // Placement new (not an allocation).
1444
+ def = new (def)
1445
+ PyModuleDef{/* m_base */ PyModuleDef_HEAD_INIT,
1446
+ /* m_name */ name,
1447
+ /* m_doc */ options::show_user_defined_docstrings () ? doc : nullptr ,
1448
+ /* m_size */ 0 ,
1449
+ /* m_methods */ nullptr ,
1450
+ /* m_slots */ slots,
1451
+ /* m_traverse */ nullptr ,
1452
+ /* m_clear */ nullptr ,
1453
+ /* m_free */ nullptr };
1454
+ auto *m = PyModuleDef_Init (def);
1455
+ if (m == nullptr ) {
1456
+ if (PyErr_Occurred ()) {
1457
+ throw error_already_set ();
1458
+ }
1459
+ pybind11_fail (" Internal error in module_::initialize_multiphase_module_def()" );
1460
+ }
1461
+ return reinterpret_borrow<object>(m);
1462
+ }
1392
1463
};
1393
1464
1394
1465
PYBIND11_NAMESPACE_BEGIN (detail)
0 commit comments