Add an event loop
This commit is contained in:
parent
380e962bd1
commit
a2e6d9e185
@ -38,7 +38,7 @@ static PyMethodDef PyThing_methods[] = {
|
|||||||
{nullptr, nullptr, 0, nullptr} // sentinel
|
{nullptr, nullptr, 0, nullptr} // sentinel
|
||||||
};
|
};
|
||||||
|
|
||||||
static PyTypeObject PyThingDiscoveryInfoType = {
|
static PyTypeObject PyThingType = {
|
||||||
PyVarObject_HEAD_INIT(NULL, 0)
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
"nymea.Thing", /* tp_name */
|
"nymea.Thing", /* tp_name */
|
||||||
sizeof(PyThing), /* tp_basicsize */
|
sizeof(PyThing), /* tp_basicsize */
|
||||||
|
|||||||
@ -52,8 +52,8 @@ static PyObject * PyThingSetupInfo_finish(PyThingSetupInfo* self, PyObject* args
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static PyMethodDef PyThingDiscoveryInfo_methods[] = {
|
static PyMethodDef PyThingSetupInfo_methods[] = {
|
||||||
{ "finish", (PyCFunction)PyThingDiscoveryInfo_finish, METH_VARARGS, "finish a discovery" },
|
{ "finish", (PyCFunction)PyThingSetupInfo_finish, METH_VARARGS, "finish a setup" },
|
||||||
{nullptr, nullptr, 0, nullptr} // sentinel
|
{nullptr, nullptr, 0, nullptr} // sentinel
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
#include <Python.h>
|
#include <Python.h>
|
||||||
#include "python/pythingdiscoveryinfo.h"
|
#include "python/pythingdiscoveryinfo.h"
|
||||||
|
#include "python/pythingsetupinfo.h"
|
||||||
|
|
||||||
#include "pythonintegrationplugin.h"
|
#include "pythonintegrationplugin.h"
|
||||||
|
|
||||||
@ -8,6 +9,7 @@
|
|||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QMetaEnum>
|
#include <QMetaEnum>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
|
#include <QtConcurrent/QtConcurrentRun>
|
||||||
|
|
||||||
QHash<PyObject*, PyThreadState*> s_modules;
|
QHash<PyObject*, PyThreadState*> s_modules;
|
||||||
|
|
||||||
@ -152,6 +154,22 @@ bool PythonIntegrationPlugin::loadScript(const QString &scriptFile)
|
|||||||
|
|
||||||
s_modules.insert(m_module, m_interpreter);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,8 +195,12 @@ void PythonIntegrationPlugin::init()
|
|||||||
|
|
||||||
void PythonIntegrationPlugin::discoverThings(ThingDiscoveryInfo *info)
|
void PythonIntegrationPlugin::discoverThings(ThingDiscoveryInfo *info)
|
||||||
{
|
{
|
||||||
|
|
||||||
PyThreadState_Swap(m_interpreter);
|
PyThreadState_Swap(m_interpreter);
|
||||||
|
|
||||||
|
PyGILState_STATE s = PyGILState_Ensure();
|
||||||
|
|
||||||
|
|
||||||
qCDebug(dcThingManager()) << "Python wrapper: discoverThings()" << info;
|
qCDebug(dcThingManager()) << "Python wrapper: discoverThings()" << info;
|
||||||
PyObject *pFunc = PyObject_GetAttrString(m_module, "discoverThings");
|
PyObject *pFunc = PyObject_GetAttrString(m_module, "discoverThings");
|
||||||
if(!pFunc || !PyCallable_Check(pFunc)) {
|
if(!pFunc || !PyCallable_Check(pFunc)) {
|
||||||
@ -194,26 +216,48 @@ void PythonIntegrationPlugin::discoverThings(ThingDiscoveryInfo *info)
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// PyObject *loop = PyObject_GetAttrString(m_module, "_loop");
|
PyObject *future = PyObject_CallFunctionObjArgs(pFunc, pyInfo, nullptr);
|
||||||
// dumpError();
|
dumpError();
|
||||||
// qWarning() << "loop:" << loop;
|
|
||||||
|
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);
|
PyObject *future = PyObject_CallFunctionObjArgs(pFunc, pyInfo, nullptr);
|
||||||
dumpError();
|
dumpError();
|
||||||
|
|
||||||
qWarning() << "future:" << future;
|
|
||||||
|
|
||||||
PyObject *asyncio = PyObject_GetAttrString(m_module, "asyncio");
|
PyObject *asyncio = PyObject_GetAttrString(m_module, "asyncio");
|
||||||
qWarning() << "ayncio:" << asyncio;
|
|
||||||
|
|
||||||
PyObject *loop = PyObject_GetAttrString(m_module, "loop");
|
PyObject *loop = PyObject_GetAttrString(m_module, "loop");
|
||||||
PyObject *create_task = PyObject_GetAttrString(loop, "create_task");
|
PyObject *run_coroutine_threadsafe = PyObject_GetAttrString(asyncio, "run_coroutine_threadsafe");
|
||||||
PyObject *task = PyObject_CallFunctionObjArgs(create_task, future, nullptr);
|
PyObject_CallFunctionObjArgs(run_coroutine_threadsafe, future, loop, nullptr);
|
||||||
|
|
||||||
dumpError();
|
|
||||||
qWarning() << "Create task:" << task;
|
|
||||||
|
|
||||||
|
PyGILState_Release(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PythonIntegrationPlugin::dumpError()
|
void PythonIntegrationPlugin::dumpError()
|
||||||
|
|||||||
@ -27,6 +27,7 @@ public:
|
|||||||
|
|
||||||
void init() override;
|
void init() override;
|
||||||
void discoverThings(ThingDiscoveryInfo *info) override;
|
void discoverThings(ThingDiscoveryInfo *info) override;
|
||||||
|
void setupThing(ThingSetupInfo *info) override;
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
Reference in New Issue
Block a user