mirror of https://github.com/nymea/nymea.git
Add an event loop
parent
380e962bd1
commit
a2e6d9e185
|
|
@ -38,7 +38,7 @@ static PyMethodDef PyThing_methods[] = {
|
|||
{nullptr, nullptr, 0, nullptr} // sentinel
|
||||
};
|
||||
|
||||
static PyTypeObject PyThingDiscoveryInfoType = {
|
||||
static PyTypeObject PyThingType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"nymea.Thing", /* tp_name */
|
||||
sizeof(PyThing), /* tp_basicsize */
|
||||
|
|
|
|||
|
|
@ -52,8 +52,8 @@ static PyObject * PyThingSetupInfo_finish(PyThingSetupInfo* self, PyObject* args
|
|||
}
|
||||
|
||||
|
||||
static PyMethodDef PyThingDiscoveryInfo_methods[] = {
|
||||
{ "finish", (PyCFunction)PyThingDiscoveryInfo_finish, METH_VARARGS, "finish a discovery" },
|
||||
static PyMethodDef PyThingSetupInfo_methods[] = {
|
||||
{ "finish", (PyCFunction)PyThingSetupInfo_finish, METH_VARARGS, "finish a setup" },
|
||||
{nullptr, nullptr, 0, nullptr} // sentinel
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include <Python.h>
|
||||
#include "python/pythingdiscoveryinfo.h"
|
||||
#include "python/pythingsetupinfo.h"
|
||||
|
||||
#include "pythonintegrationplugin.h"
|
||||
|
||||
|
|
@ -8,6 +9,7 @@
|
|||
#include <QFileInfo>
|
||||
#include <QMetaEnum>
|
||||
#include <QJsonDocument>
|
||||
#include <QtConcurrent/QtConcurrentRun>
|
||||
|
||||
QHash<PyObject*, PyThreadState*> s_modules;
|
||||
|
||||
|
|
@ -152,6 +154,22 @@ bool PythonIntegrationPlugin::loadScript(const QString &scriptFile)
|
|||
|
||||
s_modules.insert(m_module, m_interpreter);
|
||||
|
||||
QtConcurrent::run([=](){
|
||||
PyObject *loop = PyObject_GetAttrString(m_module, "loop");
|
||||
dumpError();
|
||||
// PyObject *stop = PyObject_GetAttrString(loop, "stop");
|
||||
// PyObject *call_soon = PyObject_GetAttrString(loop, "call_soon");
|
||||
PyObject *run_forever = PyObject_GetAttrString(loop, "run_forever");
|
||||
// PyObject *run_until_complete = PyObject_GetAttrString(loop, "run_until_complete");
|
||||
qCDebug(dcThingManager()) << "Starting python event loop";
|
||||
dumpError();
|
||||
PyObject_CallFunctionObjArgs(run_forever, nullptr);
|
||||
qCDebug(dcThingManager()) << "stopped python event loop";
|
||||
dumpError();
|
||||
|
||||
});
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -177,8 +195,12 @@ void PythonIntegrationPlugin::init()
|
|||
|
||||
void PythonIntegrationPlugin::discoverThings(ThingDiscoveryInfo *info)
|
||||
{
|
||||
|
||||
PyThreadState_Swap(m_interpreter);
|
||||
|
||||
PyGILState_STATE s = PyGILState_Ensure();
|
||||
|
||||
|
||||
qCDebug(dcThingManager()) << "Python wrapper: discoverThings()" << info;
|
||||
PyObject *pFunc = PyObject_GetAttrString(m_module, "discoverThings");
|
||||
if(!pFunc || !PyCallable_Check(pFunc)) {
|
||||
|
|
@ -194,26 +216,48 @@ void PythonIntegrationPlugin::discoverThings(ThingDiscoveryInfo *info)
|
|||
});
|
||||
|
||||
|
||||
// PyObject *loop = PyObject_GetAttrString(m_module, "_loop");
|
||||
// dumpError();
|
||||
// qWarning() << "loop:" << loop;
|
||||
PyObject *future = PyObject_CallFunctionObjArgs(pFunc, pyInfo, nullptr);
|
||||
dumpError();
|
||||
|
||||
PyObject *asyncio = PyObject_GetAttrString(m_module, "asyncio");
|
||||
PyObject *loop = PyObject_GetAttrString(m_module, "loop");
|
||||
PyObject *run_coroutine_threadsafe = PyObject_GetAttrString(asyncio, "run_coroutine_threadsafe");
|
||||
PyObject_CallFunctionObjArgs(run_coroutine_threadsafe, future, loop, nullptr);
|
||||
|
||||
PyGILState_Release(s);
|
||||
|
||||
}
|
||||
|
||||
void PythonIntegrationPlugin::setupThing(ThingSetupInfo *info)
|
||||
{
|
||||
PyThreadState_Swap(m_interpreter);
|
||||
|
||||
PyGILState_STATE s = PyGILState_Ensure();
|
||||
|
||||
qCDebug(dcThingManager()) << "Python wrapper: setupThing()" << info;
|
||||
PyObject *pFunc = PyObject_GetAttrString(m_module, "setupThing");
|
||||
if(!pFunc || !PyCallable_Check(pFunc)) {
|
||||
qCWarning(dcThingManager()) << "Python plugin does not implement \"setThing()\" method.";
|
||||
return;
|
||||
}
|
||||
|
||||
PyThingSetupInfo *pyInfo = (PyThingSetupInfo*)_PyObject_New(&PyThingSetupInfoType);
|
||||
pyInfo->ptrObj = info;
|
||||
|
||||
connect(info, &ThingSetupInfo::finished, this, [=](){
|
||||
PyObject_Free(pyInfo);
|
||||
});
|
||||
|
||||
|
||||
PyObject *future = PyObject_CallFunctionObjArgs(pFunc, pyInfo, nullptr);
|
||||
dumpError();
|
||||
|
||||
qWarning() << "future:" << future;
|
||||
|
||||
PyObject *asyncio = PyObject_GetAttrString(m_module, "asyncio");
|
||||
qWarning() << "ayncio:" << asyncio;
|
||||
|
||||
PyObject *loop = PyObject_GetAttrString(m_module, "loop");
|
||||
PyObject *create_task = PyObject_GetAttrString(loop, "create_task");
|
||||
PyObject *task = PyObject_CallFunctionObjArgs(create_task, future, nullptr);
|
||||
|
||||
dumpError();
|
||||
qWarning() << "Create task:" << task;
|
||||
PyObject *run_coroutine_threadsafe = PyObject_GetAttrString(asyncio, "run_coroutine_threadsafe");
|
||||
PyObject_CallFunctionObjArgs(run_coroutine_threadsafe, future, loop, nullptr);
|
||||
|
||||
PyGILState_Release(s);
|
||||
}
|
||||
|
||||
void PythonIntegrationPlugin::dumpError()
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ public:
|
|||
|
||||
void init() override;
|
||||
void discoverThings(ThingDiscoveryInfo *info) override;
|
||||
void setupThing(ThingSetupInfo *info) override;
|
||||
|
||||
|
||||
private:
|
||||
|
|
|
|||
Loading…
Reference in New Issue