some more work

This commit is contained in:
Michael Zanetti 2020-06-17 23:38:44 +02:00
parent 68e9c82758
commit 59c1c8e9f2
2 changed files with 47 additions and 33 deletions

View File

@ -5,6 +5,7 @@
#include "structmember.h" #include "structmember.h"
#include "integrations/thing.h" #include "integrations/thing.h"
#include "loggingcategories.h"
#include <QPointer> #include <QPointer>
@ -18,16 +19,12 @@ typedef struct _thing {
} PyThing; } PyThing;
static int PyThing_init(PyThing */*self*/, PyObject */*args*/, PyObject */*kwds*/) static int PyThing_init(PyThing */*self*/, PyObject */*args*/, PyObject */*kwds*/) {
// initialize PyVoice Object
{
return 0; return 0;
} }
static void PyThing_dealloc(PyThing * self) static void PyThing_dealloc(PyThing * self) {
// destruct the object
{
// FIXME: Why is this not called? Seems we're leaking... // FIXME: Why is this not called? Seems we're leaking...
Q_ASSERT(false); Q_ASSERT(false);
Py_TYPE(self)->tp_free(self); Py_TYPE(self)->tp_free(self);
@ -53,12 +50,12 @@ static int PyThing_setName(PyThing *self, PyObject *value, void */*closure*/){
static PyObject * PyThing_setStateValue(PyThing* self, PyObject* args) static PyObject * PyThing_setStateValue(PyThing* self, PyObject* args)
{ {
char *stateTypeIdStr; char *stateTypeIdStr = nullptr;
PyObject *valueObj; PyObject *valueObj = nullptr;
// FIXME: is there any better way to do this? Value is a variant // FIXME: is there any better way to do this? Value is a variant
if (!PyArg_ParseTuple(args, "sO", &stateTypeIdStr, &valueObj)) { if (!PyArg_ParseTuple(args, "sO", &stateTypeIdStr, &valueObj)) {
qWarning() << "error parsing parameters"; qCWarning(dcThingManager) << "Error parsing parameters";
return nullptr; return nullptr;
} }
@ -68,7 +65,6 @@ static PyObject * PyThing_setStateValue(PyThing* self, PyObject* args)
PyObject* str = PyUnicode_AsEncodedString(repr, "utf-8", "~E~"); PyObject* str = PyUnicode_AsEncodedString(repr, "utf-8", "~E~");
const char *bytes = PyBytes_AS_STRING(str); const char *bytes = PyBytes_AS_STRING(str);
qWarning() << "params:" << stateTypeId << bytes << self;
QVariant value(bytes); QVariant value(bytes);
if (self->ptrObj != nullptr) { if (self->ptrObj != nullptr) {
@ -81,6 +77,37 @@ static PyObject * PyThing_setStateValue(PyThing* self, PyObject* args)
Py_RETURN_NONE; Py_RETURN_NONE;
} }
static PyObject * PyThing_emitEvent(PyThing* self, PyObject* args)
{
char *eventTypeIdStr = nullptr;
PyObject *valueObj = nullptr;
if (!PyArg_ParseTuple(args, "s|O", &eventTypeIdStr, &valueObj)) {
qCWarning(dcThingManager) << "Error parsing parameters";
return nullptr;
}
EventTypeId eventTypeId = EventTypeId(eventTypeIdStr);
// if (valueObj != nullptr) {
// PyObject* repr = PyObject_Repr(valueObj);
// PyObject* str = PyUnicode_AsEncodedString(repr, "utf-8", "~E~");
// const char *bytes = PyBytes_AS_STRING(str);
// QVariant value(bytes);
// }
if (self->ptrObj != nullptr) {
QMetaObject::invokeMethod(self->ptrObj, "emitEvent", Qt::QueuedConnection, Q_ARG(EventTypeId, eventTypeId));
}
// Py_XDECREF(repr);
// Py_XDECREF(str);
Py_RETURN_NONE;
}
static PyGetSetDef PyThing_getseters[] = { static PyGetSetDef PyThing_getseters[] = {
{"name", (getter)PyThing_getName, (setter)PyThing_setName, "Thingname", nullptr}, {"name", (getter)PyThing_getName, (setter)PyThing_setName, "Thingname", nullptr},
{nullptr , nullptr, nullptr, nullptr, nullptr} /* Sentinel */ {nullptr , nullptr, nullptr, nullptr, nullptr} /* Sentinel */
@ -88,7 +115,7 @@ static PyGetSetDef PyThing_getseters[] = {
static PyMethodDef PyThing_methods[] = { static PyMethodDef PyThing_methods[] = {
{ "setStateValue", (PyCFunction)PyThing_setStateValue, METH_VARARGS, "Set a things state value" }, { "setStateValue", (PyCFunction)PyThing_setStateValue, METH_VARARGS, "Set a things state value" },
// { "finish", (PyCFunction)PyThing_finish, METH_VARARGS, "finish a discovery" }, { "emitEvent", (PyCFunction)PyThing_emitEvent, METH_VARARGS, "Emits an event" },
{nullptr, nullptr, 0, nullptr} // sentinel {nullptr, nullptr, 0, nullptr} // sentinel
}; };

View File

@ -126,23 +126,10 @@ void PythonIntegrationPlugin::initPython()
// Import nymea module into this interpreter // Import nymea module into this interpreter
s_nymeaModule = PyImport_ImportModule("nymea"); s_nymeaModule = PyImport_ImportModule("nymea");
// We'll be using asyncio everywhere, so let's import it right away
// // Spawn a event loop for python
s_asyncio = PyImport_ImportModule("asyncio"); s_asyncio = PyImport_ImportModule("asyncio");
// PyObject *get_event_loop = PyObject_GetAttrString(s_asyncio, "get_event_loop");
// PyObject *loop = PyObject_CallFunctionObjArgs(get_event_loop, nullptr);
// PyObject *run_forever = PyObject_GetAttrString(loop, "run_forever");
// Need to release ths lock from the main thread before spawning new threads
// QtConcurrent::run([=](){
// PyGILState_STATE s = PyGILState_Ensure();
// PyObject_CallFunctionObjArgs(run_forever, nullptr);
// PyGILState_Release(s);
// });
// Need to release ths lock from the main thread before spawning the new thread
s_mainThread = PyEval_SaveThread(); s_mainThread = PyEval_SaveThread();
} }
@ -408,14 +395,14 @@ void PythonIntegrationPlugin::exportBrowserItemActionTypes(const ActionTypes &ac
void PythonIntegrationPlugin::callPluginFunction(const QString &function, PyObject *param) void PythonIntegrationPlugin::callPluginFunction(const QString &function, PyObject *param)
{ {
PyEval_RestoreThread(s_mainThread); PyGILState_STATE s = PyGILState_Ensure();
qCDebug(dcThingManager()) << "Calling python plugin function" << function; qCDebug(dcThingManager()) << "Calling python plugin function" << function;
PyObject *pFunc = PyObject_GetAttrString(m_module, function.toUtf8()); PyObject *pFunc = PyObject_GetAttrString(m_module, function.toUtf8());
if(!pFunc || !PyCallable_Check(pFunc)) { if(!pFunc || !PyCallable_Check(pFunc)) {
Py_XDECREF(pFunc); Py_XDECREF(pFunc);
qCWarning(dcThingManager()) << "Python plugin does not implement" << function; qCWarning(dcThingManager()) << "Python plugin does not implement" << function;
s_mainThread = PyEval_SaveThread(); PyGILState_Release(s);
return; return;
} }
@ -429,12 +416,12 @@ void PythonIntegrationPlugin::callPluginFunction(const QString &function, PyObje
if (PyErr_Occurred()) { if (PyErr_Occurred()) {
qCWarning(dcThingManager()) << "Error calling python method:"; qCWarning(dcThingManager()) << "Error calling python method:";
dumpError(); dumpError();
s_mainThread = PyEval_SaveThread(); PyGILState_Release(s);
return; return;
} }
if (QByteArray(future->ob_type->tp_name) != "coroutine") { if (QByteArray(future->ob_type->tp_name) != "coroutine") {
s_mainThread = PyEval_SaveThread(); PyGILState_Release(s);
return; return;
} }
@ -453,10 +440,10 @@ void PythonIntegrationPlugin::callPluginFunction(const QString &function, PyObje
PyObject *result = PyObject_CallFunctionObjArgs(add_done_callback, task_done, nullptr); PyObject *result = PyObject_CallFunctionObjArgs(add_done_callback, task_done, nullptr);
dumpError(); dumpError();
PyObject *run_forever = PyObject_GetAttrString(loop, "run_until_complete"); PyObject *run_until_complete = PyObject_GetAttrString(loop, "run_until_complete");
QtConcurrent::run([=](){ QtConcurrent::run([=](){
PyGILState_STATE s = PyGILState_Ensure(); PyGILState_STATE s = PyGILState_Ensure();
PyObject_CallFunctionObjArgs(run_forever, task, nullptr); PyObject_CallFunctionObjArgs(run_until_complete, task, nullptr);
PyGILState_Release(s); PyGILState_Release(s);
}); });
@ -467,6 +454,6 @@ void PythonIntegrationPlugin::callPluginFunction(const QString &function, PyObje
Py_DECREF(add_done_callback); Py_DECREF(add_done_callback);
Py_DECREF(result); Py_DECREF(result);
s_mainThread = PyEval_SaveThread(); PyGILState_Release(s);
} }