some more work
This commit is contained in:
parent
68e9c82758
commit
59c1c8e9f2
@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user