File indexing completed on 2026-05-31 08:32:27
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #pragma once
0011
0012 #include "pybind11.h"
0013 #include "eval.h"
0014
0015 #include <memory>
0016 #include <vector>
0017
0018 #if defined(PYPY_VERSION)
0019 # error Embedding the interpreter is not supported with PyPy
0020 #endif
0021
0022 #define PYBIND11_EMBEDDED_MODULE_IMPL(name) \
0023 extern "C" PyObject *pybind11_init_impl_##name(); \
0024 extern "C" PyObject *pybind11_init_impl_##name() { return pybind11_init_wrapper_##name(); }
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058 PYBIND11_WARNING_PUSH
0059 PYBIND11_WARNING_DISABLE_CLANG("-Wgnu-zero-variadic-macro-arguments")
0060 #define PYBIND11_EMBEDDED_MODULE(name, variable, ...) \
0061 PYBIND11_MODULE_PYINIT(name, {}, ##__VA_ARGS__) \
0062 ::pybind11::detail::embedded_module PYBIND11_CONCAT(pybind11_module_, name)( \
0063 PYBIND11_TOSTRING(name), PYBIND11_CONCAT(PyInit_, name)); \
0064 PYBIND11_MODULE_EXEC(name, variable)
0065 PYBIND11_WARNING_POP
0066
0067 PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
0068 PYBIND11_NAMESPACE_BEGIN(detail)
0069
0070
0071 struct embedded_module {
0072 using init_t = PyObject *(*) ();
0073 embedded_module(const char *name, init_t init) {
0074 if (Py_IsInitialized() != 0) {
0075 pybind11_fail("Can't add new modules after the interpreter has been initialized");
0076 }
0077
0078 auto result = PyImport_AppendInittab(name, init);
0079 if (result == -1) {
0080 pybind11_fail("Insufficient memory to add a new module");
0081 }
0082 }
0083 };
0084
0085 struct wide_char_arg_deleter {
0086 void operator()(wchar_t *ptr) const {
0087
0088 PyMem_RawFree(ptr);
0089 }
0090 };
0091
0092 inline wchar_t *widen_chars(const char *safe_arg) {
0093 wchar_t *widened_arg = Py_DecodeLocale(safe_arg, nullptr);
0094 return widened_arg;
0095 }
0096
0097 inline void precheck_interpreter() {
0098 if (Py_IsInitialized() != 0) {
0099 pybind11_fail("The interpreter is already running");
0100 }
0101 }
0102
0103 #if !defined(PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX)
0104 # define PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX (0x03080000)
0105 #endif
0106
0107 #if PY_VERSION_HEX < PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX
0108 inline void initialize_interpreter_pre_pyconfig(bool init_signal_handlers,
0109 int argc,
0110 const char *const *argv,
0111 bool add_program_dir_to_path) {
0112 detail::precheck_interpreter();
0113 Py_InitializeEx(init_signal_handlers ? 1 : 0);
0114
0115 auto argv_size = static_cast<size_t>(argc);
0116
0117 std::unique_ptr<wchar_t *[]> widened_argv(new wchar_t *[argv_size]);
0118 std::vector<std::unique_ptr<wchar_t[], detail::wide_char_arg_deleter>> widened_argv_entries;
0119 widened_argv_entries.reserve(argv_size);
0120 for (size_t ii = 0; ii < argv_size; ++ii) {
0121 widened_argv_entries.emplace_back(detail::widen_chars(argv[ii]));
0122 if (!widened_argv_entries.back()) {
0123
0124
0125 return;
0126 }
0127 widened_argv[ii] = widened_argv_entries.back().get();
0128 }
0129
0130 auto *pysys_argv = widened_argv.get();
0131
0132 PySys_SetArgvEx(argc, pysys_argv, static_cast<int>(add_program_dir_to_path));
0133 }
0134 #endif
0135
0136 PYBIND11_NAMESPACE_END(detail)
0137
0138 #if PY_VERSION_HEX >= PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX
0139 inline void initialize_interpreter(PyConfig *config,
0140 int argc = 0,
0141 const char *const *argv = nullptr,
0142 bool add_program_dir_to_path = true) {
0143 detail::precheck_interpreter();
0144 PyStatus status = PyConfig_SetBytesArgv(config, argc, const_cast<char *const *>(argv));
0145 if (PyStatus_Exception(status) != 0) {
0146
0147
0148 PyConfig_Clear(config);
0149 throw std::runtime_error(PyStatus_IsError(status) != 0 ? status.err_msg
0150 : "Failed to prepare CPython");
0151 }
0152 status = Py_InitializeFromConfig(config);
0153 if (PyStatus_Exception(status) != 0) {
0154 PyConfig_Clear(config);
0155 throw std::runtime_error(PyStatus_IsError(status) != 0 ? status.err_msg
0156 : "Failed to init CPython");
0157 }
0158 if (add_program_dir_to_path) {
0159 PyRun_SimpleString("import sys, os.path; "
0160 "sys.path.insert(0, "
0161 "os.path.abspath(os.path.dirname(sys.argv[0])) "
0162 "if sys.argv and os.path.exists(sys.argv[0]) else '')");
0163 }
0164 PyConfig_Clear(config);
0165 }
0166 #endif
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187 inline void initialize_interpreter(bool init_signal_handlers = true,
0188 int argc = 0,
0189 const char *const *argv = nullptr,
0190 bool add_program_dir_to_path = true) {
0191 #if PY_VERSION_HEX < PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX
0192 detail::initialize_interpreter_pre_pyconfig(
0193 init_signal_handlers, argc, argv, add_program_dir_to_path);
0194 #else
0195 PyConfig config;
0196 PyConfig_InitPythonConfig(&config);
0197
0198 config.parse_argv = 0;
0199
0200 config.install_signal_handlers = init_signal_handlers ? 1 : 0;
0201 initialize_interpreter(&config, argc, argv, add_program_dir_to_path);
0202 #endif
0203
0204
0205 detail::get_num_interpreters_seen() = 1;
0206 }
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243 inline void finalize_interpreter() {
0244
0245 if (detail::get_num_interpreters_seen() > 1) {
0246 detail::get_internals_pp_manager().unref();
0247 detail::get_local_internals_pp_manager().unref();
0248
0249
0250 detail::get_num_interpreters_seen() = 1;
0251 }
0252
0253
0254
0255
0256
0257 detail::get_internals_pp_manager().get_pp();
0258 detail::get_local_internals_pp_manager().get_pp();
0259
0260 Py_Finalize();
0261
0262 detail::get_internals_pp_manager().destroy();
0263
0264
0265
0266 detail::get_local_internals_pp_manager().destroy();
0267
0268
0269 detail::get_num_interpreters_seen() = 0;
0270 }
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287 class scoped_interpreter {
0288 public:
0289 explicit scoped_interpreter(bool init_signal_handlers = true,
0290 int argc = 0,
0291 const char *const *argv = nullptr,
0292 bool add_program_dir_to_path = true) {
0293 initialize_interpreter(init_signal_handlers, argc, argv, add_program_dir_to_path);
0294 }
0295
0296 #if PY_VERSION_HEX >= PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX
0297 explicit scoped_interpreter(PyConfig *config,
0298 int argc = 0,
0299 const char *const *argv = nullptr,
0300 bool add_program_dir_to_path = true) {
0301 initialize_interpreter(config, argc, argv, add_program_dir_to_path);
0302 }
0303 #endif
0304
0305 scoped_interpreter(const scoped_interpreter &) = delete;
0306 scoped_interpreter(scoped_interpreter &&other) noexcept { other.is_valid = false; }
0307 scoped_interpreter &operator=(const scoped_interpreter &) = delete;
0308 scoped_interpreter &operator=(scoped_interpreter &&) = delete;
0309
0310 ~scoped_interpreter() {
0311 if (is_valid) {
0312 finalize_interpreter();
0313 }
0314 }
0315
0316 private:
0317 bool is_valid = true;
0318 };
0319
0320 PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)