From 051c14fe7235893d64edd65de0bd62d19ab68a4d Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Tue, 25 Sep 2018 19:27:23 +0100 Subject: [PATCH] Add working version of IOrganizer::waitForApplication (#18) --- src/runner/pythonrunner.cpp | 52 +++++++++++++++++++++++++++++++++++++ src/runner/uibasewrappers.h | 5 ++-- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/src/runner/pythonrunner.cpp b/src/runner/pythonrunner.cpp index cc4a8cf..5eedfb8 100644 --- a/src/runner/pythonrunner.cpp +++ b/src/runner/pythonrunner.cpp @@ -119,6 +119,44 @@ struct QString_from_python_str }; +struct HANDLE_converters +{ + struct HANDLE_to_python + { + static PyObject *convert(HANDLE handle) { + size_t size_t_version = (size_t)handle; + return bpy::incref(bpy::object(size_t_version).ptr()); + } + }; + + // bpy isn't keen on actually using this. + // maybe it's detecting that the function receives a pointer, and assumes that it needs to convert to the pointer's target. + // the issue can be worked around by wrapping the function to take a size_t and converting it there + struct HANDLE_from_python + { + HANDLE_from_python() { + bpy::converter::registry::push_back(&convertible, &construct, bpy::type_id()); + } + + static void *convertible(PyObject *objPtr) { + return PyLong_Check(objPtr) ? objPtr : nullptr; + } + + static void construct(PyObject *objPtr, bpy::converter::rvalue_from_python_stage1_data *data) { + void *storage = ((bpy::converter::rvalue_from_python_storage*)data)->storage.bytes; + HANDLE *result = new (storage) HANDLE; + *result = (HANDLE)bpy::extract(objPtr)(); + } + }; + + HANDLE_converters() + { + HANDLE_from_python(); + bpy::to_python_converter(); + } +}; + + template struct GuessedValue_converters { @@ -794,6 +832,16 @@ struct Functor2_converter }; +// We must wrap IOrganizer::waitForApplication to convert the out parameter to a return value and also because bpy doesn't like coverting to void* (HANDLE) even if a converter exists. +static PyObject *waitForApplication(const bpy::object &self, size_t handle) +{ + IOrganizer& organizer = bpy::extract(self)(); + DWORD returnCode; + bool result = organizer.waitForApplication((HANDLE)handle, &returnCode); + return bpy::incref(bpy::make_tuple(result, returnCode).ptr()); +} + + BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(updateWithQuality, MOBase::GuessedValue::update, 2, 2) @@ -920,6 +968,8 @@ BOOST_PYTHON_MODULE(mobase) .def("profile", bpy::pure_virtual(&IOrganizer::profile), bpy::return_value_policy()) .def("startApplication", bpy::pure_virtual(&IOrganizer::startApplication), ((bpy::arg("args")=QStringList()), (bpy::arg("cwd")=""), (bpy::arg("profile")="")), bpy::return_value_policy()) //.def("waitForApplication", bpy::pure_virtual(&IOrganizer::waitForApplication), (bpy::arg("exitCode")=nullptr), bpy::return_value_policy()) + // Use wrapped version + .def("waitForApplication", waitForApplication) .def("onModInstalled", bpy::pure_virtual(&IOrganizer::onModInstalled)) .def("onAboutToRun", bpy::pure_virtual(&IOrganizer::onAboutToRun)) .def("onFinishedRun", bpy::pure_virtual(&IOrganizer::onFinishedRun)) @@ -1178,6 +1228,8 @@ BOOST_PYTHON_MODULE(mobase) GuessedValue_converters(); + HANDLE_converters(); + //bpy::to_python_converter(); QList_from_python_obj(); diff --git a/src/runner/uibasewrappers.h b/src/runner/uibasewrappers.h index c7731f9..85c6de3 100644 --- a/src/runner/uibasewrappers.h +++ b/src/runner/uibasewrappers.h @@ -201,6 +201,7 @@ private: }; +// NOTE: Completely unnecessary - we're never going to override IOrganizer from within Python struct IOrganizerWrapper : MOBase::IOrganizer, boost::python::wrapper { virtual MOBase::IModRepositoryBridge *createNexusBridge() const override @@ -324,12 +325,12 @@ struct IOrganizerWrapper : MOBase::IOrganizer, const QString &cwd = "", const QString &profile = "") override { - return reinterpret_cast(this->get_override("startApplication")(executable, args, cwd, profile).as()); + return reinterpret_cast(this->get_override("startApplication")(executable, args, cwd, profile).as()); } virtual bool waitForApplication(HANDLE handle, LPDWORD exitCode = nullptr) const override { - return this->get_override("waitForApplication")(reinterpret_cast(handle), exitCode); + return this->get_override("waitForApplication")(reinterpret_cast(handle), exitCode); } virtual void refreshModList(bool saveChanges = true) override {