Fix Python 3 crash on Windows, and fix some Python 3-related compile errors

This commit is contained in:
rdb 2014-10-10 13:45:05 +00:00
parent 296476f7dd
commit 902bedc314
6 changed files with 113 additions and 19 deletions

View File

@ -31,6 +31,9 @@
// And this is for GetModuleFileName().
#include <windows.h>
// And this is for CommandLineToArgvW.
#include <shellapi.h>
// SHGetSpecialFolderPath()
#include <shlobj.h>
#endif
@ -74,12 +77,11 @@ extern char **environ;
#define PREREAD_ENVIRONMENT
#endif
// We define the symbol HAVE_GLOBAL_ARGV if we have global variables
// named GLOBAL_ARGC/GLOBAL_ARGV that we can read at static init time
// to determine our command-line arguments.
#if defined(HAVE_GLOBAL_ARGV) && defined(PROTOTYPE_GLOBAL_ARGV)
#if !defined(WIN32_VC) && defined(HAVE_GLOBAL_ARGV) && defined(PROTOTYPE_GLOBAL_ARGV)
extern char **GLOBAL_ARGV;
extern int GLOBAL_ARGC;
#endif
@ -762,7 +764,32 @@ read_args() {
// Next we need to fill in _args, which is a vector containing
// the command-line arguments that the executable was invoked with.
#if defined(IS_FREEBSD)
#if defined(WIN32_VC)
// We cannot rely on __argv when Python is linked in Unicode mode.
// Instead, let's use GetCommandLine.
LPWSTR cmdline = GetCommandLineW();
int argc = 0;
LPWSTR *argv = CommandLineToArgvW(cmdline, &argc);
TextEncoder encoder;
encoder.set_encoding(Filename::get_filesystem_encoding());
for (int i = 0; i < argc; ++i) {
wstring wtext(argv[i]);
encoder.set_wtext(wtext);
if (i == 0) {
if (_binary_name.empty()) {
_binary_name = encoder.get_text();
}
} else {
_args.push_back(encoder.get_text());
}
}
#elif defined(IS_FREEBSD)
// In FreeBSD, we can use sysctl to determine the command-line arguments.
size_t bufsize = 4096;
@ -786,6 +813,9 @@ read_args() {
#elif defined(HAVE_GLOBAL_ARGV)
int argc = GLOBAL_ARGC;
// On Windows, __argv can be NULL when the main entry point is
// compiled in Unicode mode (as is the case with Python 3)
if (GLOBAL_ARGV != NULL) {
if (_binary_name.empty() && argc > 0) {
_binary_name = GLOBAL_ARGV[0];
// This really needs to be resolved against PATH.
@ -794,6 +824,7 @@ read_args() {
for (int i = 1; i < argc; i++) {
_args.push_back(GLOBAL_ARGV[i]);
}
}
#elif defined(HAVE_PROC_SELF_CMDLINE) || defined(HAVE_PROC_CURPROC_CMDLINE)
// In Linux, and possibly in other systems as well, we might not be

View File

@ -3292,6 +3292,21 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
expected_params += "string";
++num_params;
} else if (TypeManager::is_pointer_to_PyUnicodeObject(type)) {
if (args_type == AT_single_arg) {
// This is a single-arg function, so there's no need
// to convert anything.
param_name = "arg";
extra_param_check += " && PyUnicode_Check(arg)";
} else {
indent(out, indent_level) << "PyUnicodeObject *" << param_name << ";\n";
format_specifiers += "U";
parameter_list += ", &" + param_name;
}
pexpr_string = param_name;
expected_params += "unicode";
++num_params;
} else if (TypeManager::is_pointer_to_PyObject(type)) {
if (args_type == AT_single_arg) {
// This is a single-arg function, so there's no need

View File

@ -1251,6 +1251,45 @@ is_PyStringObject(CPPType *type) {
}
}
////////////////////////////////////////////////////////////////////
// Function: TypeManager::is_pointer_to_PyUnicodeObject
// Access: Public, Static
// Description: Returns true if the indicated type is PyStringObject *.
////////////////////////////////////////////////////////////////////
bool TypeManager::
is_pointer_to_PyUnicodeObject(CPPType *type) {
switch (type->get_subtype()) {
case CPPDeclaration::ST_const:
return is_pointer_to_PyUnicodeObject(type->as_const_type()->_wrapped_around);
case CPPDeclaration::ST_pointer:
return is_PyUnicodeObject(type->as_pointer_type()->_pointing_at);
default:
return false;
}
}
////////////////////////////////////////////////////////////////////
// Function: TypeManager::is_PyUnicodeObject
// Access: Public, Static
// Description: Returns true if the indicated type is PyUnicodeObject.
////////////////////////////////////////////////////////////////////
bool TypeManager::
is_PyUnicodeObject(CPPType *type) {
switch (type->get_subtype()) {
case CPPDeclaration::ST_const:
return is_PyUnicodeObject(type->as_const_type()->_wrapped_around);
case CPPDeclaration::ST_extension:
case CPPDeclaration::ST_struct:
return (type->get_local_name(&parser) == "PyUnicodeObject");
default:
return false;
}
}
////////////////////////////////////////////////////////////////////
// Function: TypeManager::is_pointer_to_Py_buffer
// Access: Public, Static

View File

@ -96,6 +96,8 @@ public:
static bool is_PyObject(CPPType *type);
static bool is_pointer_to_PyStringObject(CPPType *type);
static bool is_PyStringObject(CPPType *type);
static bool is_pointer_to_PyUnicodeObject(CPPType *type);
static bool is_PyUnicodeObject(CPPType *type);
static bool is_pointer_to_Py_buffer(CPPType *type);
static bool is_Py_buffer(CPPType *type);
static bool involves_unpublished(CPPType *type);

View File

@ -1882,6 +1882,8 @@ def SdkLocatePython(force_use_sys_executable = False):
py_dll = os.path.basename(py_dlls[0])
SDK["PYTHONVERSION"] = "python" + py_dll[6] + "." + py_dll[7]
os.environ["PYTHONHOME"] = SDK["PYTHON"]
elif CrossCompiling():
tp_python = os.path.join(GetThirdpartyDir(), "python")
SDK["PYTHON"] = tp_python + "/include"

View File

@ -30,8 +30,13 @@ make(PyUnicodeObject *str) {
if (!PyUnicode_CHECK_INTERNED(str)) {
// Not an interned string; don't bother.
Py_ssize_t len = 0;
char *c_str = PyUnicode_AsUTF8AndSize(str, &len);
return InternalName::make(name);
char *c_str = PyUnicode_AsUTF8AndSize((PyObject *)str, &len);
if (c_str == NULL) {
return NULL;
}
string name(c_str, len);
return InternalName::make(c_str, len);
}
InternalName::PyInternTable::const_iterator it;
@ -42,7 +47,7 @@ make(PyUnicodeObject *str) {
} else {
Py_ssize_t len = 0;
char *c_str = PyUnicode_AsUTF8AndSize(str, &len);
char *c_str = PyUnicode_AsUTF8AndSize((PyObject *)str, &len);
string name(c_str, len);
#else