Created
August 4, 2020 10:20
-
-
Save bstaletic/ba0afff792396ea438937948b2d80582 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#if PY_VERSION_MAJOR >= 3 | |
#define PYBIND11_ARGV_TYPE wchar_t** | |
#else | |
#define PYBIND11_ARGV_TYPE char** | |
#endif | |
struct wide_char_arg_deleter { | |
void operator()(void* ptr) const { | |
#if PY_VERSION_HEX >= 0x030500f0 | |
// API docs: https://docs.python.org/3/c-api/sys.html#c.Py_DecodeLocale | |
PyMem_RawFree(ptr); | |
#else | |
delete ptr; | |
#endif | |
} | |
}; | |
wchar_t* widen_chars(char* safe_arg) { | |
#if PY_VERSION_HEX >= 0x030500f0 | |
wchar_t* widened_arg = Py_DecodeLocale(safe_arg, nullptr); | |
#elif HAVE_BROKEN_MBSTOWCS | |
size_t count = strlen(safe_arg); | |
widened_arg = nullptr; | |
if (count != static_cast<size_t>(-1)) { | |
widened_arg = new wchar_t[count + 1]; | |
mbstowcs(widened_arg, safe_arg, count + 1); | |
} | |
#else | |
size_t count = mbstowcs(nullptr, safe_arg, 0); | |
widened_arg = nullptr; | |
if (count != static_cast<size_t>(-1)) { | |
widened_arg = new wchar_t[count + 1]; | |
mbstowcs(widened_arg, safe_arg, count + 1); | |
} | |
#endif | |
return widened_arg; | |
} | |
inline void set_interpreter_argv(int argc, char** argv, bool add_current_dir_to_path) { | |
// Before it was special-cased in python 3.8, passing an empty or null argv | |
// caused a segfault, so we have to reimplement the special case ourselves. | |
char** safe_argv = argv; | |
std::unique_ptr<char*[]> argv_guard; | |
std::unique_ptr<char[]> argv_inner_guard; | |
if (nullptr == argv || argc <= 0) { | |
argv_guard = std::unique_ptr<char*[]>(safe_argv = new char*[1]); | |
argv_inner_guard = std::unique_ptr<char[]>(safe_argv[0] = new char[1]); | |
safe_argv[0][0] = '\0'; | |
argc = 1; | |
} | |
#if PY_MAJOR_VERSION >= 3 | |
size_t argv_size = static_cast<size_t>(argc); | |
// SetArgv* on python 3 takes wchar_t, so we have to convert. | |
std::vector< std::unique_ptr<wchar_t[], wide_char_arg_deleter> > widened_argv_entries; | |
for (size_t ii = 0; ii < argv_size; ++ii) { | |
widened_argv_entries.emplace_back(widen_chars(safe_argv[ii])); | |
if (widened_argv_entries.back()) { | |
// A null here indicates a character-encoding failure or the python | |
// interpreter out of memory. Give up. | |
return; | |
} | |
} | |
PYBIND11_ARGV_TYPE pysys_argv = widened_argv.get(); | |
#else | |
PYBIND11_ARGV_TYPE pysys_argv = safe_argv; | |
#endif | |
PySys_SetArgv(argc, pysys_argv); | |
if (!add_current_dir_to_path) | |
PyList_PopItem(py::module::import("sys").attr("path").ptr(), 0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment