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
@ -298,7 +300,7 @@ ns_get_environment_variable(const string &var) const {
#endif
}
}
PyGILState_Release(state);
if (main_dir.empty()) {
@ -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,13 +813,17 @@ read_args() {
#elif defined(HAVE_GLOBAL_ARGV)
int argc = GLOBAL_ARGC;
if (_binary_name.empty() && argc > 0) {
_binary_name = GLOBAL_ARGV[0];
// This really needs to be resolved against PATH.
}
// 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.
}
for (int i = 1; i < argc; i++) {
_args.push_back(GLOBAL_ARGV[i]);
for (int i = 1; i < argc; i++) {
_args.push_back(GLOBAL_ARGV[i]);
}
}
#elif defined(HAVE_PROC_SELF_CMDLINE) || defined(HAVE_PROC_CURPROC_CMDLINE)

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

@ -221,7 +221,7 @@ def ProgressOutput(progress, msg, target = None):
prefix = "%s[%s %d%%%s] " % (GetColor("yellow"), GetColor("cyan"), progress, GetColor("yellow"))
else:
global THREADS
ident = thread.get_ident()
if (ident not in THREADS):
THREADS[ident] = len(THREADS) + 1
@ -469,7 +469,7 @@ def LocateBinary(binary):
p = os.environ["PATH"]
pathList = p.split(os.pathsep)
if GetHost() == 'windows':
if not binary.endswith('.exe'):
# Append .exe if necessary
@ -871,7 +871,7 @@ def CxxCalcDependencies(srcfile, ipath, ignore):
########################################################################
if sys.platform == "win32":
# Note: not supported on cygwin.
# Note: not supported on cygwin.
if sys.version_info >= (3, 0):
import winreg
else:
@ -1132,7 +1132,7 @@ def GetThirdpartyBase():
THIRDPARTYBASE = "thirdparty"
if "MAKEPANDA_THIRDPARTY" in os.environ:
THIRDPARTYBASE = os.environ["MAKEPANDA_THIRDPARTY"]
return THIRDPARTYBASE
def GetThirdpartyDir():
@ -1853,7 +1853,7 @@ def SdkLocatePython(force_use_sys_executable = False):
force_use_sys_executable = False
if (GetTarget() == 'windows' and not force_use_sys_executable):
SDK["PYTHON"] = GetThirdpartyBase()+"/win-python"
SDK["PYTHON"] = GetThirdpartyBase() + "/win-python"
if (GetOptimize() <= 2):
SDK["PYTHON"] += "-dbg"
if (GetTargetArch() == 'x64' and os.path.isdir(SDK["PYTHON"] + "-x64")):
@ -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"
@ -2804,4 +2806,4 @@ def TargetAdd(target, dummy=0, opts=0, input=0, dep=0, ipath=0, winrc=0):
t.deps[FindLocation("dtool_have_python.dat", [])] = 1
if target.endswith(".pz") and not CrossCompiling():
t.deps[FindLocation("pzip.exe", [])] = 1
t.deps[FindLocation("pzip.exe", [])] = 1

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