diff --git a/api/mraa/gpio.h b/api/mraa/gpio.h index 33be5ea..ef14734 100644 --- a/api/mraa/gpio.h +++ b/api/mraa/gpio.h @@ -40,10 +40,6 @@ extern "C" { #endif -#ifdef SWIGPYTHON -#include -#endif - #include #include #include "common.h" diff --git a/include/python/mraapy.h b/include/python/mraapy.h new file mode 100644 index 0000000..d48fc4e --- /dev/null +++ b/include/python/mraapy.h @@ -0,0 +1,27 @@ +/* + * Author: Henry Bruce + * Copyright (c) 2016 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#pragma once + +void mraa_python_isr(void (*isr)(void*), void* isr_args); diff --git a/src/mraa.c b/src/mraa.c index d484cae..5bbfcfa 100644 --- a/src/mraa.c +++ b/src/mraa.c @@ -99,13 +99,6 @@ mraa_init() syslog(LOG_NOTICE, "libmraa version %s initialised by user '%s' with EUID %d", mraa_get_version(), (proc_user != NULL) ? proc_user->pw_name : "", proc_euid); -#ifdef SWIGPYTHON - // Initialise python threads, this allows use to grab the GIL when we are - // required to do so - Py_InitializeEx(0); - PyEval_InitThreads(); -#endif - mraa_platform_t platform_type; #if defined(X86PLAT) // Use runtime x86 platform detection diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index 1d06b82..c51ccd1 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -1,7 +1,5 @@ find_package (PythonLibs ${PYTHONBUILD_VERSION} REQUIRED) -INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH}) - include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/.. ${PYTHON_INCLUDE_DIRS} @@ -9,8 +7,8 @@ include_directories( set_source_files_properties (mraa.i PROPERTIES CPLUSPLUS ON) set_source_files_properties (mraa.i PROPERTIES SWIG_FLAGS "-I${CMAKE_BINARY_DIR}/src") -swig_add_module (python-mraa python mraa.i ${mraa_LIB_SRCS}) -swig_link_libraries (python-mraa ${PYTHON_LIBRARIES} ${mraa_LIBS}) +swig_add_module (python-mraa python mraa.i mraapy.c) +swig_link_libraries (python-mraa ${PYTHON_LIBRARIES} mraa) if (DOXYGEN_FOUND) foreach (_file ${DOCCLASSES}) diff --git a/src/python/mraa.i b/src/python/mraa.i index 64d086e..c028107 100644 --- a/src/python/mraa.i +++ b/src/python/mraa.i @@ -149,6 +149,17 @@ class Spi; %include ../mraa.i %init %{ - //Adding mraa_init() to the module initialisation process - mraa_init(); + #include "python/mraapy.h" + #include "mraa_lang_func.h" + extern mraa_lang_func_t* lang_func; + // Initialise python threads, this allows use to grab the GIL when we are + // required to do so + Py_InitializeEx(0); + PyEval_InitThreads(); + // Add mraa_init() to the module initialisation process and set isr function + mraa_result_t res = mraa_init(); + if (res == MRAA_SUCCESS || res == MRAA_ERROR_PLATFORM_ALREADY_INITIALISED) { + lang_func->python_isr = &mraa_python_isr; + } + %} diff --git a/src/python/mraapy.c b/src/python/mraapy.c new file mode 100644 index 0000000..84b8c36 --- /dev/null +++ b/src/python/mraapy.c @@ -0,0 +1,91 @@ +/* + * Author: Henry Bruce + * Copyright (c) 2016 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include "python/mraapy.h" + + +// In order to call a python object (all python functions are objects) we +// need to aquire the GIL (Global Interpreter Lock). This may not always be +// necessary but especially if doing IO (like print()) python will segfault +// if we do not hold a lock on the GIL +void +mraa_python_isr(void (*isr)(void*), void* isr_args) +{ + + PyGILState_STATE gilstate = PyGILState_Ensure(); + PyObject* arglist; + PyObject* ret; + arglist = Py_BuildValue("(O)", isr_args); + if (arglist == NULL) { + syslog(LOG_ERR, "gpio: Py_BuildValue NULL"); + } else { + ret = PyEval_CallObject((PyObject*) isr, arglist); + if (ret == NULL) { + syslog(LOG_ERR, "gpio: PyEval_CallObject failed"); + PyObject *pvalue, *ptype, *ptraceback; + PyObject *pvalue_pystr, *ptype_pystr, *ptraceback_pystr; + char *pvalue_cstr, *ptype_cstr, *ptraceback_cstr; + PyErr_Fetch(&pvalue, &ptype, &ptraceback); + pvalue_pystr = PyObject_Str(pvalue); + ptype_pystr = PyObject_Str(ptype); + ptraceback_pystr = PyObject_Str(ptraceback); +// Python2 +#if PY_VERSION_HEX < 0x03000000 + pvalue_cstr = PyString_AsString(pvalue_pystr); + ptype_cstr = PyString_AsString(ptype_pystr); + ptraceback_cstr = PyString_AsString(ptraceback_pystr); +// Python 3 and up +#elif PY_VERSION_HEX >= 0x03000000 + // In Python 3 we need one extra conversion + PyObject *pvalue_ustr, *ptype_ustr, *ptraceback_ustr; + pvalue_ustr = PyUnicode_AsUTF8String(pvalue_pystr); + pvalue_cstr = PyBytes_AsString(pvalue_ustr); + ptype_ustr = PyUnicode_AsUTF8String(ptype_pystr); + ptype_cstr = PyBytes_AsString(ptype_ustr); + ptraceback_ustr = PyUnicode_AsUTF8String(ptraceback_pystr); + ptraceback_cstr = PyBytes_AsString(ptraceback_ustr); +#endif // PY_VERSION_HEX + syslog(LOG_ERR, "gpio: the error was %s:%s:%s", pvalue_cstr, ptype_cstr, ptraceback_cstr); + Py_XDECREF(pvalue); + Py_XDECREF(ptype); + Py_XDECREF(ptraceback); + Py_XDECREF(pvalue_pystr); + Py_XDECREF(ptype_pystr); + Py_XDECREF(ptraceback_pystr); +// Python 3 and up +#if PY_VERSION_HEX >= 0x03000000 + Py_XDECREF(pvalue_ustr); + Py_XDECREF(ptype_ustr); + Py_XDECREF(ptraceback_ustr); +#endif // PY_VERSION_HEX + } else { + Py_DECREF(ret); + } + Py_DECREF(arglist); + } + + PyGILState_Release(gilstate); +}