|
@@ -54,16 +54,26 @@ P3DPythonRun(const char *program_name, const char *archive_file,
|
|
|
_interactive_console = interactive_console;
|
|
_interactive_console = interactive_console;
|
|
|
|
|
|
|
|
if (program_name != NULL) {
|
|
if (program_name != NULL) {
|
|
|
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
|
|
|
+ // Python 3 case: we have to convert it to a wstring.
|
|
|
|
|
+ TextEncoder enc;
|
|
|
|
|
+ enc.set_text(program_name);
|
|
|
|
|
+ _program_name = enc.get_wtext();
|
|
|
|
|
+#else
|
|
|
|
|
+ // Python 2 is happy with a regular string.
|
|
|
_program_name = program_name;
|
|
_program_name = program_name;
|
|
|
|
|
+#endif
|
|
|
}
|
|
}
|
|
|
if (archive_file != NULL) {
|
|
if (archive_file != NULL) {
|
|
|
_archive_file = Filename::from_os_specific(archive_file);
|
|
_archive_file = Filename::from_os_specific(archive_file);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
_py_argc = 1;
|
|
_py_argc = 1;
|
|
|
- _py_argv = (char **)malloc(2 * sizeof(char *));
|
|
|
|
|
-
|
|
|
|
|
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
|
|
|
+ _py_argv[0] = (wchar_t *)_program_name.c_str();
|
|
|
|
|
+#else
|
|
|
_py_argv[0] = (char *)_program_name.c_str();
|
|
_py_argv[0] = (char *)_program_name.c_str();
|
|
|
|
|
+#endif
|
|
|
_py_argv[1] = NULL;
|
|
_py_argv[1] = NULL;
|
|
|
|
|
|
|
|
#ifdef NDEBUG
|
|
#ifdef NDEBUG
|
|
@@ -78,7 +88,11 @@ P3DPythonRun(const char *program_name, const char *archive_file,
|
|
|
|
|
|
|
|
// Initialize Python. It appears to be important to do this before
|
|
// Initialize Python. It appears to be important to do this before
|
|
|
// we open the pipe streams and spawn the thread, below.
|
|
// we open the pipe streams and spawn the thread, below.
|
|
|
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
|
|
|
+ Py_SetProgramName((wchar_t *)_program_name.c_str());
|
|
|
|
|
+#else
|
|
|
Py_SetProgramName((char *)_program_name.c_str());
|
|
Py_SetProgramName((char *)_program_name.c_str());
|
|
|
|
|
+#endif
|
|
|
Py_Initialize();
|
|
Py_Initialize();
|
|
|
PyEval_InitThreads();
|
|
PyEval_InitThreads();
|
|
|
PySys_SetArgv(_py_argc, _py_argv);
|
|
PySys_SetArgv(_py_argc, _py_argv);
|
|
@@ -290,7 +304,20 @@ run_python() {
|
|
|
"Send an asynchronous request to the plugin host" },
|
|
"Send an asynchronous request to the plugin host" },
|
|
|
{ NULL, NULL, 0, NULL } /* Sentinel */
|
|
{ NULL, NULL, 0, NULL } /* Sentinel */
|
|
|
};
|
|
};
|
|
|
|
|
+
|
|
|
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
|
|
|
+ static PyModuleDef p3dpython_module = {
|
|
|
|
|
+ PyModuleDef_HEAD_INIT,
|
|
|
|
|
+ "p3dpython",
|
|
|
|
|
+ NULL,
|
|
|
|
|
+ -1,
|
|
|
|
|
+ p3dpython_methods,
|
|
|
|
|
+ NULL, NULL, NULL, NULL
|
|
|
|
|
+ };
|
|
|
|
|
+ PyObject *p3dpython = PyModule_Create(&p3dpython_module);
|
|
|
|
|
+#else
|
|
|
PyObject *p3dpython = Py_InitModule("p3dpython", p3dpython_methods);
|
|
PyObject *p3dpython = Py_InitModule("p3dpython", p3dpython_methods);
|
|
|
|
|
+#endif
|
|
|
if (p3dpython == NULL) {
|
|
if (p3dpython == NULL) {
|
|
|
PyErr_Print();
|
|
PyErr_Print();
|
|
|
return false;
|
|
return false;
|
|
@@ -644,8 +671,11 @@ handle_pyobj_command(TiXmlElement *xcommand, bool needs_response,
|
|
|
result = PyBool_FromLong(PyObject_IsTrue(obj));
|
|
result = PyBool_FromLong(PyObject_IsTrue(obj));
|
|
|
|
|
|
|
|
} else if (strcmp(method_name, "__int__") == 0) {
|
|
} else if (strcmp(method_name, "__int__") == 0) {
|
|
|
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
|
|
|
+ result = PyNumber_Long(obj);
|
|
|
|
|
+#else
|
|
|
result = PyNumber_Int(obj);
|
|
result = PyNumber_Int(obj);
|
|
|
-
|
|
|
|
|
|
|
+#endif
|
|
|
} else if (strcmp(method_name, "__float__") == 0) {
|
|
} else if (strcmp(method_name, "__float__") == 0) {
|
|
|
result = PyNumber_Float(obj);
|
|
result = PyNumber_Float(obj);
|
|
|
|
|
|
|
@@ -1510,10 +1540,12 @@ pyobj_to_xml(PyObject *value) {
|
|
|
xvalue->SetAttribute("type", "bool");
|
|
xvalue->SetAttribute("type", "bool");
|
|
|
xvalue->SetAttribute("value", PyObject_IsTrue(value));
|
|
xvalue->SetAttribute("value", PyObject_IsTrue(value));
|
|
|
|
|
|
|
|
|
|
+#if PY_MAJOR_VERSION < 3
|
|
|
} else if (PyInt_Check(value)) {
|
|
} else if (PyInt_Check(value)) {
|
|
|
// A plain integer value.
|
|
// A plain integer value.
|
|
|
xvalue->SetAttribute("type", "int");
|
|
xvalue->SetAttribute("type", "int");
|
|
|
xvalue->SetAttribute("value", PyInt_AsLong(value));
|
|
xvalue->SetAttribute("value", PyInt_AsLong(value));
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
} else if (PyLong_Check(value)) {
|
|
} else if (PyLong_Check(value)) {
|
|
|
// A long integer value. This gets converted either as an integer
|
|
// A long integer value. This gets converted either as an integer
|
|
@@ -1535,9 +1567,21 @@ pyobj_to_xml(PyObject *value) {
|
|
|
xvalue->SetAttribute("type", "float");
|
|
xvalue->SetAttribute("type", "float");
|
|
|
xvalue->SetDoubleAttribute("value", PyFloat_AsDouble(value));
|
|
xvalue->SetDoubleAttribute("value", PyFloat_AsDouble(value));
|
|
|
|
|
|
|
|
|
|
+
|
|
|
} else if (PyUnicode_Check(value)) {
|
|
} else if (PyUnicode_Check(value)) {
|
|
|
// A unicode value. Convert to utf-8 for the XML encoding.
|
|
// A unicode value. Convert to utf-8 for the XML encoding.
|
|
|
xvalue->SetAttribute("type", "string");
|
|
xvalue->SetAttribute("type", "string");
|
|
|
|
|
+
|
|
|
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
|
|
|
+ // In Python 3, there are only unicode strings, and there is a
|
|
|
|
|
+ // handy function for getting the UTF-8 encoded version.
|
|
|
|
|
+ Py_ssize_t length = 0;
|
|
|
|
|
+ char *buffer = PyUnicode_AsUTF8AndSize(value, &length);
|
|
|
|
|
+ if (buffer != NULL) {
|
|
|
|
|
+ string str(buffer, length);
|
|
|
|
|
+ xvalue->SetAttribute("value", str);
|
|
|
|
|
+ }
|
|
|
|
|
+#else
|
|
|
PyObject *as_str = PyUnicode_AsUTF8String(value);
|
|
PyObject *as_str = PyUnicode_AsUTF8String(value);
|
|
|
if (as_str != NULL) {
|
|
if (as_str != NULL) {
|
|
|
char *buffer;
|
|
char *buffer;
|
|
@@ -1571,6 +1615,7 @@ pyobj_to_xml(PyObject *value) {
|
|
|
}
|
|
}
|
|
|
Py_DECREF(ustr);
|
|
Py_DECREF(ustr);
|
|
|
}
|
|
}
|
|
|
|
|
+#endif // PY_MAJOR_VERSION
|
|
|
|
|
|
|
|
} else if (PyTuple_Check(value)) {
|
|
} else if (PyTuple_Check(value)) {
|
|
|
// An immutable sequence. Pass it as a concrete.
|
|
// An immutable sequence. Pass it as a concrete.
|
|
@@ -1609,7 +1654,11 @@ pyobj_to_xml(PyObject *value) {
|
|
|
PyObject *as_str;
|
|
PyObject *as_str;
|
|
|
if (PyUnicode_Check(a)) {
|
|
if (PyUnicode_Check(a)) {
|
|
|
// The key is a unicode value.
|
|
// The key is a unicode value.
|
|
|
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
|
|
|
+ as_str = a;
|
|
|
|
|
+#else
|
|
|
as_str = PyUnicode_AsUTF8String(a);
|
|
as_str = PyUnicode_AsUTF8String(a);
|
|
|
|
|
+#endif
|
|
|
} else {
|
|
} else {
|
|
|
// The key is a string value or something else. Make it
|
|
// The key is a string value or something else. Make it
|
|
|
// a string.
|
|
// a string.
|
|
@@ -1617,7 +1666,12 @@ pyobj_to_xml(PyObject *value) {
|
|
|
}
|
|
}
|
|
|
char *buffer;
|
|
char *buffer;
|
|
|
Py_ssize_t length;
|
|
Py_ssize_t length;
|
|
|
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
|
|
|
+ buffer = PyUnicode_AsUTF8AndSize(as_str, &length);
|
|
|
|
|
+ if (buffer != NULL) {
|
|
|
|
|
+#else
|
|
|
if (PyString_AsStringAndSize(as_str, &buffer, &length) != -1) {
|
|
if (PyString_AsStringAndSize(as_str, &buffer, &length) != -1) {
|
|
|
|
|
+#endif
|
|
|
string str(buffer, length);
|
|
string str(buffer, length);
|
|
|
xitem->SetAttribute("key", str);
|
|
xitem->SetAttribute("key", str);
|
|
|
}
|
|
}
|
|
@@ -1702,7 +1756,11 @@ xml_to_pyobj(TiXmlElement *xvalue) {
|
|
|
} else if (strcmp(type, "int") == 0) {
|
|
} else if (strcmp(type, "int") == 0) {
|
|
|
int value;
|
|
int value;
|
|
|
if (xvalue->QueryIntAttribute("value", &value) == TIXML_SUCCESS) {
|
|
if (xvalue->QueryIntAttribute("value", &value) == TIXML_SUCCESS) {
|
|
|
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
|
|
|
+ return PyLong_FromLong(value);
|
|
|
|
|
+#else
|
|
|
return PyInt_FromLong(value);
|
|
return PyInt_FromLong(value);
|
|
|
|
|
+#endif
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
} else if (strcmp(type, "float") == 0) {
|
|
} else if (strcmp(type, "float") == 0) {
|