diff --git a/include/java/mraajni.h b/include/java/mraajni.h index 771d8b4..339fc3d 100644 --- a/include/java/mraajni.h +++ b/include/java/mraajni.h @@ -1,6 +1,6 @@ /* - * Author: Henry bruce - * Copyright (c) 2014 Intel Corporation. + * Author: Henry Bruce + * Copyright (c) 2014-2016 Intel Corporation. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ extern "C" { #include "mraa/types.h" void mraa_java_set_jvm(JavaVM* vm); -void mraa_java_isr_callback(void *args); +void mraa_java_isr_callback(void* args); mraa_result_t mraa_java_attach_thread(); void mraa_java_detach_thread(); void* mraa_java_create_global_ref(void* args); @@ -41,4 +41,3 @@ void mraa_java_delete_global_ref(void* ref); #ifdef __cplusplus } #endif - diff --git a/include/mraa_internal.h b/include/mraa_internal.h index 428876d..fbbb567 100644 --- a/include/mraa_internal.h +++ b/include/mraa_internal.h @@ -34,9 +34,11 @@ extern "C" { #include "common.h" #include "mraa_internal_types.h" #include "mraa_adv_func.h" +#include "mraa_lang_func.h" extern mraa_board_t* plat; extern mraa_iio_info_t* plat_iio; +extern mraa_lang_func_t* lang_func; /** * Takes in pin information and sets up the multiplexors. diff --git a/include/mraa_lang_func.h b/include/mraa_lang_func.h new file mode 100644 index 0000000..9c11710 --- /dev/null +++ b/include/mraa_lang_func.h @@ -0,0 +1,35 @@ +/* + * 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 + +typedef struct { + void (*python_isr)(void (*isr)(void*), void* isr_args); + void (*java_isr_callback)(void *args); + mraa_result_t (*java_attach_thread)(); + void (*java_detach_thread)(); + void* (*java_create_global_ref)(void* args); + void (*java_delete_global_ref)(void* ref); + +} mraa_lang_func_t; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6e2aa15..fef5b57 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -175,15 +175,6 @@ if (BUILDSWIG) add_subdirectory (python) endif () if (BUILDSWIGJAVA) - FIND_PACKAGE (JNI REQUIRED) - include_directories ( - ${JAVA_INCLUDE_PATH} - ${JAVA_INCLUDE_PATH2} - ${CMAKE_CURRENT_SOURCE_DIR}/.. - ) - set (mraa_LIB_SRCS ${mraa_LIB_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/java/mraajni.c) - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive -DJAVACALLBACK") - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DJAVACALLBACK") add_subdirectory (java) endif () if (BUILDSWIGNODE) diff --git a/src/gpio/gpio.c b/src/gpio/gpio.c index e89666b..8ae30fc 100644 --- a/src/gpio/gpio.c +++ b/src/gpio/gpio.c @@ -24,9 +24,6 @@ */ #include "gpio.h" #include "mraa_internal.h" -#if defined(SWIGJAVA) || defined(JAVACALLBACK) -#include "java/mraajni.h" -#endif #include #include @@ -268,15 +265,15 @@ mraa_gpio_interrupt_handler(void* arg) dev->isr_value_fp = fp; -#if defined(SWIGJAVA) || defined(JAVACALLBACK) - if(dev->isr == mraa_java_isr_callback) { - if (mraa_java_attach_thread() != MRAA_SUCCESS) { - close(dev->isr_value_fp); - dev->isr_value_fp = -1; - return NULL; + if (lang_func->java_attach_thread != NULL) { + if (dev->isr == lang_func->java_isr_callback) { + if (lang_func->java_attach_thread() != MRAA_SUCCESS) { + close(dev->isr_value_fp); + dev->isr_value_fp = -1; + return NULL; + } } } -#endif for (;;) { if (IS_FUNC_DEFINED(dev, gpio_wait_interrupt_replace)) { @@ -292,71 +289,11 @@ mraa_gpio_interrupt_handler(void* arg) #ifdef HAVE_PTHREAD_CANCEL pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); #endif -#ifdef SWIGPYTHON - // 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 - PyGILState_STATE gilstate = PyGILState_Ensure(); - PyObject* arglist; - PyObject* ret; - arglist = Py_BuildValue("(O)", dev->isr_args); - if (arglist == NULL) { - syslog(LOG_ERR, "gpio: Py_BuildValue NULL"); + if (lang_func->python_isr != NULL) { + lang_func->python_isr(dev->isr, dev->isr_args); } else { - ret = PyEval_CallObject((PyObject*) dev->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); + dev->isr(dev->isr_args); } - - PyGILState_Release(gilstate); -#else - dev->isr(dev->isr_args); -#endif #ifdef HAVE_PTHREAD_CANCEL pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); #endif @@ -369,12 +306,14 @@ mraa_gpio_interrupt_handler(void* arg) close(dev->isr_value_fp); dev->isr_value_fp = -1; } -#if defined(SWIGJAVA) || defined(JAVACALLBACK) - if(dev->isr == mraa_java_isr_callback) { - mraa_java_delete_global_ref(dev->isr_args); - mraa_java_detach_thread(); + + if (lang_func->java_detach_thread != NULL && lang_func->java_delete_global_ref != NULL) { + if (dev->isr == lang_func->java_isr_callback) { + lang_func->java_delete_global_ref(dev->isr_args); + lang_func->java_detach_thread(); + } } -#endif + return NULL; } } @@ -442,13 +381,15 @@ mraa_gpio_isr(mraa_gpio_context dev, mraa_gpio_edge_t mode, void (*fptr)(void*), } dev->isr = fptr; -#if defined(SWIGJAVA) || defined(JAVACALLBACK) - /* Most UPM sensors use the C API, the global ref must be created here. */ + + /* Most UPM sensors use the C API, the Java global ref must be created here. */ /* The reason for checking the callback function is internal callbacks. */ - if (fptr == mraa_java_isr_callback) { - args = mraa_java_create_global_ref(args); + if (lang_func->java_create_global_ref != NULL) { + if (dev->isr == lang_func->java_isr_callback) { + args = lang_func->java_create_global_ref(args); + } } -#endif + dev->isr_args = args; pthread_create(&dev->thread_id, NULL, mraa_gpio_interrupt_handler, (void*) dev); diff --git a/src/java/CMakeLists.txt b/src/java/CMakeLists.txt index c6a2897..e38a2d3 100644 --- a/src/java/CMakeLists.txt +++ b/src/java/CMakeLists.txt @@ -1,3 +1,10 @@ +FIND_PACKAGE (JNI REQUIRED) +include_directories ( + ${JAVA_INCLUDE_PATH} + ${JAVA_INCLUDE_PATH2} + ${CMAKE_CURRENT_SOURCE_DIR}/.. +) + # SWIG treats SWIG_FLAGS as a list and not a string so semicolon seperation is required set_source_files_properties (mraajava.i PROPERTIES SWIG_FLAGS ";-package;mraa;-I${CMAKE_BINARY_DIR}/src") set_source_files_properties (mraajava.i PROPERTIES CPLUSPLUS ON) @@ -17,7 +24,7 @@ else () set (JAR $ENV{JAVA_HOME_NATIVE}/bin/jar) endif () -swig_add_module (mraajava java mraajava.i) +swig_add_module (mraajava java mraajava.i mraajni.c) swig_link_libraries (mraajava ${JAVA_LIBRARIES} mraa) add_custom_command (TARGET mraajava diff --git a/src/java/mraajava.i b/src/java/mraajava.i index 25d0a01..ac56b09 100644 --- a/src/java/mraajava.i +++ b/src/java/mraajava.i @@ -66,12 +66,21 @@ class Spi; %wrapper %{ #include "java/mraajni.h" + #include "mraa_lang_func.h" + extern mraa_lang_func_t* lang_func; jint JNI_OnLoad(JavaVM *vm, void *reserved) { - /* initialize mraa */ - mraa_java_set_jvm(vm); - mraa_init(); - return JNI_VERSION_1_6; + /* initialize mraa and set jni functions */ + mraa_result_t res = mraa_init(); + if (res == MRAA_SUCCESS || res == MRAA_ERROR_PLATFORM_ALREADY_INITIALISED) { + mraa_java_set_jvm(vm); + lang_func->java_isr_callback = &mraa_java_isr_callback; + lang_func->java_attach_thread = &mraa_java_attach_thread; + lang_func->java_detach_thread = &mraa_java_detach_thread; + lang_func->java_create_global_ref = &mraa_java_create_global_ref; + lang_func->java_delete_global_ref = &mraa_java_delete_global_ref; + } + return JNI_VERSION_1_8; } %} diff --git a/src/java/mraajni.c b/src/java/mraajni.c index 1c09cbb..63672fb 100644 --- a/src/java/mraajni.c +++ b/src/java/mraajni.c @@ -41,11 +41,11 @@ static void mraa_java_make_env_key(void) { if (globVM != NULL) { - JNIEnv *jenv; - (*globVM)->GetEnv(globVM, (void **)&jenv, JNI_VERSION_1_8); + JNIEnv* jenv; + (*globVM)->GetEnv(globVM, (void**) &jenv, JNI_VERSION_1_8); jclass rcls = (*jenv)->FindClass(jenv, "java/lang/Runnable"); jmethodID runm = (*jenv)->GetMethodID(jenv, rcls, "run", "()V"); - runGlobal = (jmethodID)(*jenv)->NewGlobalRef(jenv, (jobject)runm); + runGlobal = (jmethodID)(*jenv)->NewGlobalRef(jenv, (jobject) runm); pthread_key_create(&env_key, NULL); } } @@ -53,16 +53,16 @@ mraa_java_make_env_key(void) void mraa_java_isr_callback(void* data) { - JNIEnv *jenv = (JNIEnv *) pthread_getspecific(env_key); - (*jenv)->CallVoidMethod(jenv, (jobject)data, runGlobal); + JNIEnv* jenv = (JNIEnv*) pthread_getspecific(env_key); + (*jenv)->CallVoidMethod(jenv, (jobject) data, runGlobal); } mraa_result_t mraa_java_attach_thread() { if (globVM != NULL) { - JNIEnv *jenv; - jint err = (*globVM)->AttachCurrentThreadAsDaemon(globVM, (void **)&jenv, NULL); + JNIEnv* jenv; + jint err = (*globVM)->AttachCurrentThreadAsDaemon(globVM, (void**) &jenv, NULL); if (err == JNI_OK) { pthread_once(&env_key_init, mraa_java_make_env_key); pthread_setspecific(env_key, jenv); @@ -83,21 +83,20 @@ void* mraa_java_create_global_ref(void* args) { if (globVM != NULL) { - JNIEnv *jenv; - (*globVM)->GetEnv(globVM, (void **)&jenv, JNI_VERSION_1_8); + JNIEnv* jenv; + (*globVM)->GetEnv(globVM, (void**) &jenv, JNI_VERSION_1_8); jobject grunnable = (*jenv)->NewGlobalRef(jenv, (jobject) args); - return (void *)grunnable; + return (void*) grunnable; } else return NULL; } void -mraa_java_delete_global_ref(void *ref) +mraa_java_delete_global_ref(void* ref) { if (globVM != NULL) { - JNIEnv *jenv; - (*globVM)->GetEnv(globVM, (void **)&jenv, JNI_VERSION_1_8); - (*jenv)->DeleteGlobalRef(jenv, (jobject)ref); + JNIEnv* jenv; + (*globVM)->GetEnv(globVM, (void**) &jenv, JNI_VERSION_1_8); + (*jenv)->DeleteGlobalRef(jenv, (jobject) ref); } } - diff --git a/src/mraa.c b/src/mraa.c index b8bc236..d484cae 100644 --- a/src/mraa.c +++ b/src/mraa.c @@ -48,6 +48,7 @@ #define IIO_DEVICE_WILDCARD "iio:device*" mraa_board_t* plat = NULL; mraa_iio_info_t* plat_iio = NULL; +mraa_lang_func_t* lang_func = NULL; static char* platform_name = NULL; static char* platform_long_name = NULL; @@ -163,6 +164,8 @@ mraa_init() } } + lang_func = (mraa_lang_func_t*) calloc(1, sizeof(mraa_lang_func_t)); + syslog(LOG_NOTICE, "libmraa initialised for platform '%s' of type %d", mraa_get_platform_name(), mraa_get_platform_type()); return MRAA_SUCCESS; }