@@ -125,47 +125,6 @@ inline wchar_t *widen_chars(const char *safe_arg) {
125
125
return widened_arg;
126
126
}
127
127
128
- // / Python 2.x/3.x-compatible version of `PySys_SetArgv`
129
- inline void set_interpreter_argv (int argc, const char *const *argv, bool add_program_dir_to_path) {
130
- // Before it was special-cased in python 3.8, passing an empty or null argv
131
- // caused a segfault, so we have to reimplement the special case ourselves.
132
- bool special_case = (argv == nullptr || argc <= 0 );
133
-
134
- const char *const empty_argv[]{" \0 " };
135
- const char *const *safe_argv = special_case ? empty_argv : argv;
136
- if (special_case) {
137
- argc = 1 ;
138
- }
139
-
140
- auto argv_size = static_cast <size_t >(argc);
141
- #if PY_MAJOR_VERSION >= 3
142
- // SetArgv* on python 3 takes wchar_t, so we have to convert.
143
- std::unique_ptr<wchar_t *[]> widened_argv (new wchar_t *[argv_size]);
144
- std::vector<std::unique_ptr<wchar_t [], wide_char_arg_deleter>> widened_argv_entries;
145
- widened_argv_entries.reserve (argv_size);
146
- for (size_t ii = 0 ; ii < argv_size; ++ii) {
147
- widened_argv_entries.emplace_back (widen_chars (safe_argv[ii]));
148
- if (!widened_argv_entries.back ()) {
149
- // A null here indicates a character-encoding failure or the python
150
- // interpreter out of memory. Give up.
151
- return ;
152
- }
153
- widened_argv[ii] = widened_argv_entries.back ().get ();
154
- }
155
-
156
- auto *pysys_argv = widened_argv.get ();
157
- #else
158
- // python 2.x
159
- std::vector<std::string> strings{safe_argv, safe_argv + argv_size};
160
- std::vector<char *> char_strings{argv_size};
161
- for (std::size_t i = 0 ; i < argv_size; ++i)
162
- char_strings[i] = &strings[i][0 ];
163
- char **pysys_argv = char_strings.data ();
164
- #endif
165
-
166
- PySys_SetArgvEx (argc, pysys_argv, static_cast <int >(add_program_dir_to_path));
167
- }
168
-
169
128
PYBIND11_NAMESPACE_END (detail)
170
129
171
130
/* * \rst
@@ -195,9 +154,64 @@ inline void initialize_interpreter(bool init_signal_handlers = true,
195
154
pybind11_fail (" The interpreter is already running" );
196
155
}
197
156
157
+ #if PY_VERSION_HEX < 0x030B0000
158
+
198
159
Py_InitializeEx (init_signal_handlers ? 1 : 0 );
199
160
200
- detail::set_interpreter_argv (argc, argv, add_program_dir_to_path);
161
+ // Before it was special-cased in python 3.8, passing an empty or null argv
162
+ // caused a segfault, so we have to reimplement the special case ourselves.
163
+ bool special_case = (argv == nullptr || argc <= 0 );
164
+
165
+ const char *const empty_argv[]{" \0 " };
166
+ const char *const *safe_argv = special_case ? empty_argv : argv;
167
+ if (special_case) {
168
+ argc = 1 ;
169
+ }
170
+
171
+ auto argv_size = static_cast <size_t >(argc);
172
+ // SetArgv* on python 3 takes wchar_t, so we have to convert.
173
+ std::unique_ptr<wchar_t *[]> widened_argv (new wchar_t *[argv_size]);
174
+ std::vector<std::unique_ptr<wchar_t [], detail::wide_char_arg_deleter>> widened_argv_entries;
175
+ widened_argv_entries.reserve (argv_size);
176
+ for (size_t ii = 0 ; ii < argv_size; ++ii) {
177
+ widened_argv_entries.emplace_back (detail::widen_chars (safe_argv[ii]));
178
+ if (!widened_argv_entries.back ()) {
179
+ // A null here indicates a character-encoding failure or the python
180
+ // interpreter out of memory. Give up.
181
+ return ;
182
+ }
183
+ widened_argv[ii] = widened_argv_entries.back ().get ();
184
+ }
185
+
186
+ auto *pysys_argv = widened_argv.get ();
187
+
188
+ PySys_SetArgvEx (argc, pysys_argv, static_cast <int >(add_program_dir_to_path));
189
+ #else
190
+ PyConfig config;
191
+ PyConfig_InitIsolatedConfig (&config);
192
+ config.install_signal_handlers = init_signal_handlers ? 1 : 0 ;
193
+
194
+ PyStatus status = PyConfig_SetBytesArgv (&config, argc, const_cast <char *const *>(argv));
195
+ if (PyStatus_Exception (status)) {
196
+ // A failure here indicates a character-encoding failure or the python
197
+ // interpreter out of memory. Give up.
198
+ PyConfig_Clear (&config);
199
+ throw std::runtime_error (PyStatus_IsError (status) ? status.err_msg
200
+ : " Failed to prepare CPython" );
201
+ }
202
+ status = Py_InitializeFromConfig (&config);
203
+ PyConfig_Clear (&config);
204
+ if (PyStatus_Exception (status)) {
205
+ throw std::runtime_error (PyStatus_IsError (status) ? status.err_msg
206
+ : " Failed to init CPython" );
207
+ }
208
+ if (add_program_dir_to_path) {
209
+ PyRun_SimpleString (" import sys, os.path; "
210
+ " sys.path.insert(0, "
211
+ " os.path.abspath(os.path.dirname(sys.argv[0])) "
212
+ " if sys.argv and os.path.exists(sys.argv[0]) else '')" );
213
+ }
214
+ #endif
201
215
}
202
216
203
217
/* * \rst
0 commit comments