diff --git a/include/pybind11/detail/common.h b/include/pybind11/detail/common.h index 22416b0368..f0f3c50d3d 100644 --- a/include/pybind11/detail/common.h +++ b/include/pybind11/detail/common.h @@ -464,7 +464,7 @@ PYBIND11_WARNING_POP }); } \endrst */ -#define PYBIND11_MODULE(name, variable) \ +#define PYBIND11_MODULE(name, variable, ...) \ static ::pybind11::module_::module_def PYBIND11_CONCAT(pybind11_module_def_, name) \ PYBIND11_MAYBE_UNUSED; \ PYBIND11_MAYBE_UNUSED \ @@ -473,7 +473,10 @@ PYBIND11_WARNING_POP PYBIND11_CHECK_PYTHON_VERSION \ PYBIND11_ENSURE_INTERNALS_READY \ auto m = ::pybind11::module_::create_extension_module( \ - PYBIND11_TOSTRING(name), nullptr, &PYBIND11_CONCAT(pybind11_module_def_, name)); \ + PYBIND11_TOSTRING(name), \ + nullptr, \ + &PYBIND11_CONCAT(pybind11_module_def_, name), \ + ##__VA_ARGS__); \ try { \ PYBIND11_CONCAT(pybind11_init_, name)(m); \ return m.ptr(); \ diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 6b85ba3a9a..3160d00277 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -1206,6 +1206,8 @@ struct handle_type_name { PYBIND11_NAMESPACE_END(detail) +struct gil_not_used {}; + /// Wrapper for Python extension modules class module_ : public object { public: @@ -1299,15 +1301,6 @@ class module_ : public object { PyModule_AddObject(ptr(), name, obj.inc_ref().ptr() /* steals a reference */); } - /** \rst - Mark the module as not requiring the GIL in free-threaded Python builds. - \endrst */ - void set_gil_not_used() { -#ifdef Py_GIL_DISABLED - PyUnstable_Module_SetGIL(m_ptr, Py_MOD_GIL_NOT_USED); -#endif - } - using module_def = PyModuleDef; // TODO: Can this be removed (it was needed only for Python 2)? /** \rst @@ -1316,6 +1309,20 @@ class module_ : public object { ``def`` should point to a statically allocated module_def. \endrst */ static module_ create_extension_module(const char *name, const char *doc, module_def *def) { + return _create_extension_module(name, doc, def, false); + } + + static module_ + create_extension_module(const char *name, const char *doc, module_def *def, gil_not_used) { + return _create_extension_module(name, doc, def, true); + } + +private: + static module_ _create_extension_module(const char *name, + const char *doc, + module_def *def, + bool gil_disabled) { + // module_def is PyModuleDef // Placement new (not an allocation). def = new (def) @@ -1335,6 +1342,11 @@ class module_ : public object { } pybind11_fail("Internal error in module_::create_extension_module()"); } + if (gil_disabled) { +#ifdef Py_GIL_DISABLED + PyUnstable_Module_SetGIL(m, Py_MOD_GIL_NOT_USED); +#endif + } // TODO: Should be reinterpret_steal for Python 3, but Python also steals it again when // returned from PyInit_... // For Python 2, reinterpret_borrow was correct. diff --git a/tests/eigen_tensor_avoid_stl_array.cpp b/tests/eigen_tensor_avoid_stl_array.cpp index aed1569c62..9f3c78bd92 100644 --- a/tests/eigen_tensor_avoid_stl_array.cpp +++ b/tests/eigen_tensor_avoid_stl_array.cpp @@ -11,7 +11,6 @@ #include "test_eigen_tensor.inl" -PYBIND11_MODULE(eigen_tensor_avoid_stl_array, m) { - m.set_gil_not_used(); +PYBIND11_MODULE(eigen_tensor_avoid_stl_array, m, pybind11::gil_not_used()) { eigen_tensor_test::test_module(m); } diff --git a/tests/pybind11_cross_module_tests.cpp b/tests/pybind11_cross_module_tests.cpp index f206f67bd4..5c318391d3 100644 --- a/tests/pybind11_cross_module_tests.cpp +++ b/tests/pybind11_cross_module_tests.cpp @@ -16,9 +16,7 @@ #include #include -PYBIND11_MODULE(pybind11_cross_module_tests, m) { - m.set_gil_not_used(); - +PYBIND11_MODULE(pybind11_cross_module_tests, m, py::gil_not_used()) { m.doc() = "pybind11 cross-module test module"; // test_local_bindings.py tests: diff --git a/tests/pybind11_tests.cpp b/tests/pybind11_tests.cpp index 4cd4757ead..93256edaff 100644 --- a/tests/pybind11_tests.cpp +++ b/tests/pybind11_tests.cpp @@ -75,9 +75,7 @@ const char *cpp_std() { #endif } -PYBIND11_MODULE(pybind11_tests, m) { - m.set_gil_not_used(); - +PYBIND11_MODULE(pybind11_tests, m, py::gil_not_used()) { m.doc() = "pybind11 test module"; // Intentionally kept minimal to not create a maintenance chore diff --git a/tests/test_cmake_build/main.cpp b/tests/test_cmake_build/main.cpp index 92a6e2a81d..f115406552 100644 --- a/tests/test_cmake_build/main.cpp +++ b/tests/test_cmake_build/main.cpp @@ -1,7 +1,6 @@ #include namespace py = pybind11; -PYBIND11_MODULE(test_cmake_build, m) { - m.set_gil_not_used(); +PYBIND11_MODULE(test_cmake_build, m, py::gil_not_used()) { m.def("add", [](int i, int j) { return i + j; }); } diff --git a/tests/test_embed/external_module.cpp b/tests/test_embed/external_module.cpp index 7b22391499..8a17aae245 100644 --- a/tests/test_embed/external_module.cpp +++ b/tests/test_embed/external_module.cpp @@ -6,15 +6,13 @@ namespace py = pybind11; * modules aren't preserved over a finalize/initialize. */ -PYBIND11_MODULE(external_module, m) { +PYBIND11_MODULE(external_module, m, py::gil_not_used()) { class A { public: explicit A(int value) : v{value} {}; int v; }; - m.set_gil_not_used(); - py::class_(m, "A").def(py::init()).def_readwrite("value", &A::v); m.def("internals_at",