Skip to content

Commit 0566160

Browse files
bstaleticdrmoose
authored andcommitted
Factor out wchar conversion to a separate function.
1 parent 3b8438e commit 0566160

File tree

1 file changed

+24
-22
lines changed

1 file changed

+24
-22
lines changed

include/pybind11/embed.h

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,27 @@ struct wide_char_arg_deleter {
100100
}
101101
};
102102

103+
wchar_t* widen_chars(char* safe_arg) {
104+
#if PY_VERSION_HEX >= 0x030500f0
105+
wchar_t* widened_arg = Py_DecodeLocale(safe_arg, nullptr);
106+
#elif HAVE_BROKEN_MBSTOWCS
107+
size_t count = strlen(safe_arg);
108+
widened_arg = nullptr;
109+
if (count != static_cast<size_t>(-1)) {
110+
widened_arg = new wchar_t[count + 1];
111+
mbstowcs(widened_arg, safe_arg, count + 1);
112+
}
113+
#else
114+
size_t count = mbstowcs(nullptr, safe_arg, 0);
115+
widened_arg = nullptr;
116+
if (count != static_cast<size_t>(-1)) {
117+
widened_arg = new wchar_t[count + 1];
118+
mbstowcs(widened_arg, safe_arg, count + 1);
119+
}
120+
#endif
121+
return widened_arg;
122+
}
123+
103124
/// Python 2.x/3.x-compatible version of `PySys_SetArgv`
104125
inline void set_interpreter_argv(int argc, char** argv, bool add_current_dir_to_path) {
105126
// Before it was special-cased in python 3.8, passing an empty or null argv
@@ -116,33 +137,14 @@ inline void set_interpreter_argv(int argc, char** argv, bool add_current_dir_to_
116137
#if PY_MAJOR_VERSION >= 3
117138
size_t argv_size = static_cast<size_t>(argc);
118139
// SetArgv* on python 3 takes wchar_t, so we have to convert.
119-
std::unique_ptr<wchar_t*[]> widened_argv(new wchar_t*[argv_size]);
120140
std::vector< std::unique_ptr<wchar_t[], wide_char_arg_deleter> > widened_argv_entries;
121141
for (size_t ii = 0; ii < argv_size; ++ii) {
122-
# if PY_MINOR_VERSION >= 5
123-
// From Python 3.5 onwards, we're supposed to use Py_DecodeLocale to
124-
// generate the wchar_t version of argv.
125-
widened_argv[ii] = Py_DecodeLocale(safe_argv[ii], nullptr);
126-
# else
127-
// Before Python 3.5, we're stuck with mbstowcs, which may or may not
128-
// actually work. Mercifully, pyconfig.h provides this define:
129-
# ifdef HAVE_BROKEN_MBSTOWCS
130-
size_t count = strlen(safe_argv[ii]);
131-
# else
132-
size_t count = mbstowcs(nullptr, safe_argv[ii], 0);
133-
# endif
134-
widened_argv[ii] = nullptr;
135-
if (count != static_cast<size_t>(-1)) {
136-
widened_argv[ii] = new wchar_t[count + 1];
137-
mbstowcs(widened_argv[ii], safe_argv[ii], count + 1);
138-
}
139-
# endif
140-
if (nullptr == widened_argv[ii]) {
142+
widened_argv_entries.emplace_back(widen_chars(safe_argv[ii]));
143+
if (!widened_argv_entries.back()) {
141144
// A null here indicates a character-encoding failure or the python
142145
// interpreter out of memory. Give up.
143146
return;
144-
} else
145-
widened_argv_entries.emplace_back(widened_argv[ii]);
147+
}
146148
}
147149

148150
auto pysys_argv = widened_argv.get();

0 commit comments

Comments
 (0)