@@ -1242,6 +1242,71 @@ class mod_gil_not_used {
1242
1242
bool flag_;
1243
1243
};
1244
1244
1245
+ // Use to activate Py_MOD_PER_INTERPRETER_GIL_SUPPORTED
1246
+ class mod_per_interpreter_gil {
1247
+ public:
1248
+ explicit mod_per_interpreter_gil (bool flag = true ) : flag_(flag) {}
1249
+ bool flag () const { return flag_; }
1250
+
1251
+ private:
1252
+ bool flag_;
1253
+ };
1254
+
1255
+ // Use to activate Py_MOD_MULTIPLE_INTERPRETERS_SUPPORTED
1256
+ class mod_multi_interpreter_one_gil {
1257
+ public:
1258
+ explicit mod_multi_interpreter_one_gil (bool flag = true ) : flag_(flag) {}
1259
+ bool flag () const { return flag_; }
1260
+
1261
+ private:
1262
+ bool flag_;
1263
+ };
1264
+
1265
+ PYBIND11_NAMESPACE_BEGIN (detail)
1266
+
1267
+ inline bool gil_not_used_option () { return false ; }
1268
+ template <typename F, typename ... O>
1269
+ bool gil_not_used_option (F &&, O &&...o );
1270
+ template <typename ... O>
1271
+ inline bool gil_not_used_option (mod_gil_not_used f, O &&...o ) {
1272
+ return f.flag () || gil_not_used_option (o...);
1273
+ }
1274
+ template <typename F, typename ... O>
1275
+ inline bool gil_not_used_option (F &&, O &&...o ) {
1276
+ return false || gil_not_used_option (o...);
1277
+ }
1278
+
1279
+ #ifdef Py_mod_multiple_interpreters
1280
+ inline void *multi_interp_option () { return Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED; }
1281
+ # ifdef PYBIND11_SUBINTERPRETER_SUPPORT
1282
+ template <typename F, typename ... O>
1283
+ void *multi_interp_option (F &&, O &&...o );
1284
+ template <typename ... O>
1285
+ void *multi_interp_option (mod_multi_interpreter_one_gil f, O &&...o );
1286
+ template <typename ... O>
1287
+ inline void *multi_interp_option (mod_per_interpreter_gil f, O &&...o ) {
1288
+ if (f.flag ()) {
1289
+ return Py_MOD_PER_INTERPRETER_GIL_SUPPORTED;
1290
+ }
1291
+ return multi_interp_option (o...);
1292
+ }
1293
+ template <typename ... O>
1294
+ inline void *multi_interp_option (mod_multi_interpreter_one_gil f, O &&...o ) {
1295
+ void *others = multi_interp_option (o...);
1296
+ if (!f.flag () || others == Py_MOD_PER_INTERPRETER_GIL_SUPPORTED) {
1297
+ return others;
1298
+ }
1299
+ return Py_MOD_MULTIPLE_INTERPRETERS_SUPPORTED;
1300
+ }
1301
+ # endif
1302
+ template <typename F, typename ... O>
1303
+ inline void *multi_interp_option (F &&, O &&...o ) {
1304
+ return multi_interp_option (o...);
1305
+ }
1306
+ #endif
1307
+
1308
+ PYBIND11_NAMESPACE_END (detail)
1309
+
1245
1310
// / Wrapper for Python extension modules
1246
1311
class module_ : public object {
1247
1312
public:
@@ -1376,6 +1441,73 @@ class module_ : public object {
1376
1441
// For Python 2, reinterpret_borrow was correct.
1377
1442
return reinterpret_borrow<module_>(m);
1378
1443
}
1444
+
1445
+ /* * \rst
1446
+ Initialized a module def for use with multi-phase module initialization.
1447
+
1448
+ ``def`` should point to a statically allocated module_def.
1449
+ ``slots`` must point to an initialized array of slots with space for at
1450
+ least two additional slots to be populated based on the options.
1451
+ \endrst */
1452
+ template <typename ... Options>
1453
+ static object init_module_def (const char *name,
1454
+ const char *doc,
1455
+ module_def *def,
1456
+ PyModuleDef_Slot *slots,
1457
+ Options &&...options) {
1458
+ int i = 0 ;
1459
+ while (slots[i].slot != 0 ) {
1460
+ ++i;
1461
+ }
1462
+
1463
+ bool nogil PYBIND11_MAYBE_UNUSED = detail::gil_not_used_option (options...);
1464
+ void *interp PYBIND11_MAYBE_UNUSED = detail::multi_interp_option (options...);
1465
+
1466
+ #ifdef Py_mod_multiple_interpreters
1467
+ if (nogil && interp == Py_MOD_MULTIPLE_INTERPRETERS_SUPPORTED) {
1468
+ // if you support free threading and multi-interpreters,
1469
+ // then you definitely also support per-interpreter GIL
1470
+ // even if you don't know it.
1471
+ interp = Py_MOD_PER_INTERPRETER_GIL_SUPPORTED;
1472
+ }
1473
+ slots[i].slot = Py_mod_multiple_interpreters;
1474
+ slots[i].value = interp;
1475
+ ++i;
1476
+ #endif
1477
+ #ifdef Py_mod_gil
1478
+ slots[i].slot = Py_mod_gil;
1479
+ slots[i].value = Py_MOD_GIL_USED;
1480
+ if (nogil) {
1481
+ # ifdef Py_GIL_DISABLED
1482
+ slots[i].value = Py_MOD_GIL_NOT_USED;
1483
+ # endif
1484
+ }
1485
+ ++i;
1486
+ #endif
1487
+ slots[i].slot = 0 ;
1488
+ slots[i].value = nullptr ;
1489
+
1490
+ // module_def is PyModuleDef
1491
+ // Placement new (not an allocation).
1492
+ def = new (def)
1493
+ PyModuleDef{/* m_base */ PyModuleDef_HEAD_INIT,
1494
+ /* m_name */ name,
1495
+ /* m_doc */ options::show_user_defined_docstrings () ? doc : nullptr ,
1496
+ /* m_size */ 0 ,
1497
+ /* m_methods */ nullptr ,
1498
+ /* m_slots */ slots,
1499
+ /* m_traverse */ nullptr ,
1500
+ /* m_clear */ nullptr ,
1501
+ /* m_free */ nullptr };
1502
+ auto *m = PyModuleDef_Init (def);
1503
+ if (m == nullptr ) {
1504
+ if (PyErr_Occurred ()) {
1505
+ throw error_already_set ();
1506
+ }
1507
+ pybind11_fail (" Internal error in module_::init_module_def()" );
1508
+ }
1509
+ return reinterpret_borrow<object>(m);
1510
+ }
1379
1511
};
1380
1512
1381
1513
PYBIND11_NAMESPACE_BEGIN (detail)
0 commit comments