diff --git a/dtool/src/dtoolutil/executionEnvironment.cxx b/dtool/src/dtoolutil/executionEnvironment.cxx index 41e7aae64d..fac9475d46 100644 --- a/dtool/src/dtoolutil/executionEnvironment.cxx +++ b/dtool/src/dtoolutil/executionEnvironment.cxx @@ -31,6 +31,9 @@ // And this is for GetModuleFileName(). #include +// And this is for CommandLineToArgvW. +#include + // SHGetSpecialFolderPath() #include #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) diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.cxx b/dtool/src/interrogate/interfaceMakerPythonNative.cxx index 0a1f601c12..6549bf70fc 100755 --- a/dtool/src/interrogate/interfaceMakerPythonNative.cxx +++ b/dtool/src/interrogate/interfaceMakerPythonNative.cxx @@ -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 diff --git a/dtool/src/interrogate/typeManager.cxx b/dtool/src/interrogate/typeManager.cxx index 9ae0903469..4539ae9c0a 100644 --- a/dtool/src/interrogate/typeManager.cxx +++ b/dtool/src/interrogate/typeManager.cxx @@ -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 diff --git a/dtool/src/interrogate/typeManager.h b/dtool/src/interrogate/typeManager.h index afe02fa812..974a5b3e19 100644 --- a/dtool/src/interrogate/typeManager.h +++ b/dtool/src/interrogate/typeManager.h @@ -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); diff --git a/makepanda/makepandacore.py b/makepanda/makepandacore.py index d913017317..102d2550ea 100644 --- a/makepanda/makepandacore.py +++ b/makepanda/makepandacore.py @@ -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 diff --git a/panda/src/gobj/internalName_ext.cxx b/panda/src/gobj/internalName_ext.cxx index 99bee102a9..5d15fd5e6d 100644 --- a/panda/src/gobj/internalName_ext.cxx +++ b/panda/src/gobj/internalName_ext.cxx @@ -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