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 "integrations/thing.h"
#include "loggingcategories.h"
#include <QPointer>
@ -18,16 +19,12 @@ typedef struct _thing {
} PyThing;
static int PyThing_init(PyThing */*self*/, PyObject */*args*/, PyObject */*kwds*/)
// initialize PyVoice Object
{
static int PyThing_init(PyThing */*self*/, PyObject */*args*/, PyObject */*kwds*/) {
return 0;
}
static void PyThing_dealloc(PyThing * self)
// destruct the object
{
static void PyThing_dealloc(PyThing * self) {
// FIXME: Why is this not called? Seems we're leaking...
Q_ASSERT(false);
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)
{
char *stateTypeIdStr;
PyObject *valueObj;
char *stateTypeIdStr = nullptr;
PyObject *valueObj = nullptr;
// FIXME: is there any better way to do this? Value is a variant
if (!PyArg_ParseTuple(args, "sO", &stateTypeIdStr, &valueObj)) {
qWarning() << "error parsing parameters";
qCWarning(dcThingManager) << "Error parsing parameters";
return nullptr;
}
@ -68,7 +65,6 @@ static PyObject * PyThing_setStateValue(PyThing* self, PyObject* args)
PyObject* str = PyUnicode_AsEncodedString(repr, "utf-8", "~E~");
const char *bytes = PyBytes_AS_STRING(str);
qWarning() << "params:" << stateTypeId << bytes << self;
QVariant value(bytes);
if (self->ptrObj != nullptr) {
@ -81,6 +77,37 @@ static PyObject * PyThing_setStateValue(PyThing* self, PyObject* args)
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[] = {
{"name", (getter)PyThing_getName, (setter)PyThing_setName, "Thingname", nullptr},
{nullptr , nullptr, nullptr, nullptr, nullptr} /* Sentinel */
@ -88,7 +115,7 @@ static PyGetSetDef PyThing_getseters[] = {
static PyMethodDef PyThing_methods[] = {
{ "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
};

View File

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