mirror of
https://github.com/ModOrganizer2/modorganizer-plugin_python.git
synced 2026-07-27 14:03:33 -07:00
Changes to compile and run with python3 (WIP)
This commit is contained in:
+1
-1
@@ -14,7 +14,7 @@ LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake)
|
||||
FILE(GLOB_RECURSE PYTHON_ROOT ${DEPENDENCIES_DIR}/Python*/pyconfig.h.in)
|
||||
GET_FILENAME_COMPONENT(PYTHON_ROOT ${PYTHON_ROOT} DIRECTORY)
|
||||
|
||||
FILE(GLOB_RECURSE SIP_ROOT ${DEPENDENCIES_DIR}/sip*/siplib/sip.h)
|
||||
FILE(GLOB_RECURSE SIP_ROOT ${DEPENDENCIES_DIR}/sip-*/siplib/sip.h)
|
||||
GET_FILENAME_COMPONENT(SIP_ROOT ${SIP_ROOT} DIRECTORY)
|
||||
|
||||
# need to install python
|
||||
|
||||
@@ -13,6 +13,7 @@ FILE(GLOB ${PROJ_NAME}_HDRS *.h)
|
||||
SET(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
SET(CMAKE_AUTOMOC ON)
|
||||
SET(CMAKE_AUTOUIC ON)
|
||||
ADD_DEFINITIONS(-DQT_NO_KEYWORDS)
|
||||
FIND_PACKAGE(Qt5Widgets REQUIRED)
|
||||
#QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS})
|
||||
FIND_PACKAGE(Qt5LinguistTools)
|
||||
|
||||
@@ -202,7 +202,7 @@ public:
|
||||
virtual QIcon icon() const;
|
||||
virtual void setParentWidget(QWidget *parent);
|
||||
|
||||
public slots:
|
||||
public Q_SLOTS:
|
||||
virtual void display() const;
|
||||
};
|
||||
|
||||
|
||||
+45
-36
@@ -48,7 +48,7 @@ private:
|
||||
private:
|
||||
std::map<QString, boost::python::object> m_PythonObjects;
|
||||
const MOBase::IOrganizer *m_MOInfo;
|
||||
char *m_PythonHome;
|
||||
wchar_t *m_PythonHome;
|
||||
};
|
||||
|
||||
|
||||
@@ -69,13 +69,14 @@ using namespace MOBase;
|
||||
|
||||
namespace bpy = boost::python;
|
||||
|
||||
static sipWrapperType sipWrapper_Type;
|
||||
|
||||
struct QString_to_python_str
|
||||
{
|
||||
static PyObject *convert(const QString &str) {
|
||||
// It's safer to explicitly convert to unicode as if we don't, this can return either str or unicode without it being easy to know which to expect
|
||||
bpy::object pyStr = bpy::object(str.toUtf8().constData());
|
||||
if (PyString_Check(pyStr.ptr()))
|
||||
if (SIPBytes_Check(pyStr.ptr()))
|
||||
pyStr = pyStr.attr("decode")("utf-8");
|
||||
return bpy::incref(pyStr.ptr());
|
||||
}
|
||||
@@ -97,14 +98,14 @@ struct QString_from_python_str
|
||||
}
|
||||
|
||||
static void *convertible(PyObject *objPtr) {
|
||||
return PyString_Check(objPtr) || PyUnicode_Check(objPtr) ? objPtr : nullptr;
|
||||
return SIPBytes_Check(objPtr) || PyUnicode_Check(objPtr) ? objPtr : nullptr;
|
||||
}
|
||||
|
||||
static void construct(PyObject *objPtr, bpy::converter::rvalue_from_python_stage1_data *data) {
|
||||
// Ensure the string uses 8-bit characters
|
||||
PyObject *strPtr = PyUnicode_Check(objPtr) ? PyUnicode_AsUTF8String(objPtr) : objPtr;
|
||||
// Extract the character data from the python string
|
||||
const char* value = PyString_AsString(strPtr);
|
||||
const char* value = SIPBytes_AsString(strPtr);
|
||||
// Deallocate local copy if one was made
|
||||
if (strPtr != objPtr)
|
||||
Py_DecRef(strPtr);
|
||||
@@ -225,7 +226,7 @@ struct QVariant_to_python_obj
|
||||
{
|
||||
static PyObject *convert(const QVariant &var) {
|
||||
switch (var.type()) {
|
||||
case QVariant::Int: return PyLong_FromLong(var.toInt());
|
||||
case QVariant::Int: return SIPLong_FromLong(var.toInt());
|
||||
case QVariant::UInt: return PyLong_FromUnsignedLong(var.toUInt());
|
||||
case QVariant::Bool: return PyBool_FromLong(var.toBool());
|
||||
case QVariant::String: return bpy::incref(bpy::object(var.toString()).ptr());
|
||||
@@ -251,7 +252,7 @@ struct QVariant_from_python_obj
|
||||
}
|
||||
|
||||
static void *convertible(PyObject *objPtr) {
|
||||
if (!PyString_Check(objPtr) && !PyInt_Check(objPtr) &&
|
||||
if (!SIPBytes_Check(objPtr) && !PyLong_Check(objPtr) &&
|
||||
!PyBool_Check(objPtr) && !PyList_Check(objPtr)) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -268,17 +269,17 @@ struct QVariant_from_python_obj
|
||||
}
|
||||
|
||||
static void construct(PyObject *objPtr, bpy::converter::rvalue_from_python_stage1_data *data) {
|
||||
// PyBools will also return true for PyInt_Check but not the other way around, so the order
|
||||
// PyBools will also return true for SIPLong_Check but not the other way around, so the order
|
||||
// here is relevant
|
||||
if (PyList_Check(objPtr)) {
|
||||
constructVariant(bpy::extract<QVariantList>(objPtr)(), data);
|
||||
} else if (PyDict_Check(objPtr)) {
|
||||
constructVariant(bpy::extract<QVariantMap>(objPtr)(), data);
|
||||
} else if (PyString_Check(objPtr) || PyUnicode_Check(objPtr)) {
|
||||
} else if (SIPBytes_Check(objPtr) || PyUnicode_Check(objPtr)) {
|
||||
constructVariant(bpy::extract<QString>(objPtr)(), data);
|
||||
} else if (PyBool_Check(objPtr)) {
|
||||
constructVariant(bpy::extract<bool>(objPtr)(), data);
|
||||
} else if (PyInt_Check(objPtr)) {
|
||||
} else if (SIPLong_Check(objPtr)) {
|
||||
//QVariant doesn't have long. It has int or long long. Given that on m/s,
|
||||
//long is 32 bits for 32- and 64- bit code...
|
||||
constructVariant(bpy::extract<int>(objPtr)(), data);
|
||||
@@ -399,11 +400,11 @@ struct QFlags_from_python_obj
|
||||
}
|
||||
|
||||
static void* convertible(PyObject *objPtr) {
|
||||
return PyInt_Check(objPtr) ? objPtr : nullptr;
|
||||
return SIPLong_Check(objPtr) ? objPtr : nullptr;
|
||||
}
|
||||
|
||||
static void construct(PyObject *objPtr, bpy::converter::rvalue_from_python_stage1_data *data) {
|
||||
int intVersion = (int)PyInt_AsLong(objPtr);
|
||||
int intVersion = (int)SIPLong_AsLong(objPtr);
|
||||
T tVersion = (T)intVersion;
|
||||
void *storage = ((bpy::converter::rvalue_from_python_storage<QFlags<T>> *)data)->storage.bytes;
|
||||
new (storage) QFlags<T>(tVersion);
|
||||
@@ -558,7 +559,22 @@ struct QClass_converters
|
||||
|
||||
static void *QClass_from_PyQt(PyObject *objPtr)
|
||||
{
|
||||
if (!PyObject_TypeCheck(objPtr, sipAPI()->api_simplewrapper_type)) {
|
||||
// This would transfer responsibility for deconstructing the object to C++, but Boost assumes l-value converters (such as this) don't do that
|
||||
// Instead, this should be called within the wrappers for functions which return deletable pointers.
|
||||
//sipAPI()->api_transfer_to(objPtr, 0);
|
||||
/*if (PyObject_TypeCheck(objPtr, sipAPI()->api_wrapper_type)) {
|
||||
sipWrapper *wrapper;
|
||||
wrapper = reinterpret_cast<sipWrapper*>(objPtr);
|
||||
return wrapper->super.data;
|
||||
} else if (PyObject_TypeCheck(objPtr, sipAPI()->api_simplewrapper_type)) {*/
|
||||
sipSimpleWrapper *wrapper;
|
||||
wrapper = reinterpret_cast<sipSimpleWrapper*>(objPtr);
|
||||
return wrapper->data;
|
||||
/*} else if (PyObject_TypeCheck(objPtr, sipAPI()->api_wrappertype_type)) {
|
||||
sipWrapper *wrapper;
|
||||
wrapper = reinterpret_cast<sipWrapper*>(objPtr);
|
||||
return wrapper->super.data;
|
||||
} else {
|
||||
if (std::is_same_v<T, QStringList>)
|
||||
{
|
||||
// QStringLists aren't wrapped by PyQt - regular Python string/unicode lists are used instead
|
||||
@@ -566,17 +582,13 @@ struct QClass_converters
|
||||
if (extractor.check())
|
||||
return new QStringList(extractor());
|
||||
}
|
||||
PyErr_SetString(PyExc_TypeError, "type not wrapped");
|
||||
bpy::throw_error_already_set();
|
||||
}
|
||||
|
||||
// This would transfer responsibility for deconstructing the object to C++, but Boost assumes l-value converters (such as this) don't do that
|
||||
// Instead, this should be called within the wrappers for functions which return deletable pointers.
|
||||
//sipAPI()->api_transfer_to(objPtr, 0);
|
||||
|
||||
sipSimpleWrapper *wrapper = reinterpret_cast<sipSimpleWrapper*>(objPtr);
|
||||
return wrapper->data;
|
||||
if (!std::is_same_v<T, QIcon>) {
|
||||
PyErr_SetString(PyExc_TypeError, "type not wrapped");
|
||||
bpy::throw_error_already_set();
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
QClass_converters()
|
||||
{
|
||||
bpy::converter::registry::insert(&QClass_from_PyQt, bpy::type_id<T>());
|
||||
@@ -658,7 +670,7 @@ int getArgCount(PyObject *object) {
|
||||
if (funcCode) {
|
||||
PyObject *argCount = PyObject_GetAttrString(funcCode, "co_argcount");
|
||||
if(argCount) {
|
||||
result = PyInt_AsLong(argCount);
|
||||
result = SIPLong_AsLong(argCount);
|
||||
Py_DECREF(argCount);
|
||||
}
|
||||
Py_DECREF(funcCode);
|
||||
@@ -1203,7 +1215,7 @@ BOOST_PYTHON_MODULE(mobase)
|
||||
PythonRunner::PythonRunner(const MOBase::IOrganizer *moInfo)
|
||||
: m_MOInfo(moInfo)
|
||||
{
|
||||
m_PythonHome = new char[MAX_PATH + 1];
|
||||
m_PythonHome = new wchar_t[MAX_PATH + 1];
|
||||
}
|
||||
|
||||
static const char *argv0 = "ModOrganizer.exe";
|
||||
@@ -1215,16 +1227,17 @@ bool PythonRunner::initPython(const QString &pythonPath)
|
||||
if (!pythonPath.isEmpty() && !QFile::exists(pythonPath + "/python.exe")) {
|
||||
return false;
|
||||
}
|
||||
strncpy(m_PythonHome, pythonPath.toUtf8().constData(), MAX_PATH);
|
||||
pythonPath.toWCharArray(m_PythonHome);
|
||||
if (!pythonPath.isEmpty()) {
|
||||
Py_SetPythonHome(m_PythonHome);
|
||||
}
|
||||
|
||||
char argBuffer[MAX_PATH];
|
||||
strcpy(argBuffer, argv0);
|
||||
wchar_t argBuffer[MAX_PATH];
|
||||
const size_t cSize = strlen(argv0) + 1;
|
||||
mbstowcs(argBuffer, argv0, MAX_PATH);
|
||||
|
||||
Py_SetProgramName(argBuffer);
|
||||
PyImport_AppendInittab("mobase", &initmobase);
|
||||
PyImport_AppendInittab("mobase", &PyInit_mobase);
|
||||
Py_OptimizeFlag = 2;
|
||||
Py_NoSiteFlag = 1;
|
||||
Py_InitializeEx(0);
|
||||
@@ -1233,15 +1246,15 @@ bool PythonRunner::initPython(const QString &pythonPath)
|
||||
return false;
|
||||
}
|
||||
|
||||
PySys_SetArgv(0, (char**)&argBuffer);
|
||||
PySys_SetArgv(0, (wchar_t**)&argBuffer);
|
||||
|
||||
bpy::object mainModule = bpy::import("__main__");
|
||||
bpy::object mainNamespace = mainModule.attr("__dict__");
|
||||
mainNamespace["sys"] = bpy::import("sys");
|
||||
initPath(mainNamespace);
|
||||
bpy::import("site");
|
||||
mainNamespace["cStringIO"] = bpy::import("cStringIO");
|
||||
bpy::exec("s_ErrIO = cStringIO.StringIO()\n"
|
||||
mainNamespace["io"] = bpy::import("io");
|
||||
bpy::exec("s_ErrIO = io.StringIO()\n"
|
||||
"sys.stderr = s_ErrIO",
|
||||
mainNamespace);
|
||||
return true;
|
||||
@@ -1277,11 +1290,7 @@ void PythonRunner::initPath(bpy::object &moduleNamespace)
|
||||
{
|
||||
static QString paths[] = {
|
||||
m_MOInfo->pluginDataPath(),
|
||||
QCoreApplication::applicationDirPath(),
|
||||
QCoreApplication::applicationDirPath() + "/python27.zip",
|
||||
QCoreApplication::applicationDirPath() + "/python27.zip/Lib",
|
||||
QCoreApplication::applicationDirPath() + "/python27.zip/DLLs",
|
||||
QCoreApplication::applicationDirPath() + "/python27.zip/Lib/site-packages",
|
||||
QCoreApplication::applicationDirPath()
|
||||
};
|
||||
|
||||
for (int i = 0; i < sizeof(paths) / sizeof(QString); ++i) {
|
||||
|
||||
@@ -7,7 +7,35 @@ static const sipAPIDef *sipAPI()
|
||||
{
|
||||
static const sipAPIDef *sipApi = nullptr;
|
||||
if (sipApi == nullptr) {
|
||||
#if defined(SIP_USE_PYCAPSULE)
|
||||
sipApi = (const sipAPIDef *)PyCapsule_Import("sip._C_API", 0);
|
||||
#else
|
||||
PyObject *sip_module;
|
||||
PyObject *sip_module_dict;
|
||||
PyObject *c_api;
|
||||
|
||||
/* Import the SIP module. */
|
||||
sip_module = PyImport_ImportModule("sip");
|
||||
|
||||
if (sip_module == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Get the module's dictionary. */
|
||||
sip_module_dict = PyModule_GetDict(sip_module);
|
||||
|
||||
/* Get the "_C_API" attribute. */
|
||||
c_api = PyDict_GetItemString(sip_module_dict, "_C_API");
|
||||
|
||||
if (c_api == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Sanity check that it is the right type. */
|
||||
if (!PyCObject_Check(c_api))
|
||||
return NULL;
|
||||
|
||||
/* Get the actual pointer from the object. */
|
||||
sipApi = (const sipAPIDef *)PyCObject_AsVoidPtr(c_api);
|
||||
#endif
|
||||
}
|
||||
|
||||
return sipApi;
|
||||
|
||||
@@ -105,7 +105,7 @@ private:
|
||||
|
||||
Q_DISABLE_COPY(ModRepositoryBridgeWrapper)
|
||||
|
||||
private slots:
|
||||
private Q_SLOTS:
|
||||
|
||||
void filesAvailable(int modID, QVariant userData, const QList<ModRepositoryFileInfo> &resultData)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user