diff --git a/api/mraa/gpio.h b/api/mraa/gpio.h index 2287c0c..33be5ea 100644 --- a/api/mraa/gpio.h +++ b/api/mraa/gpio.h @@ -44,15 +44,8 @@ extern "C" { #include #endif -#if defined(SWIGJAVA) || defined(JAVACALLBACK) -#include -extern JavaVM *globVM; -extern void mraa_java_isr_callback(void *); -#endif - #include #include - #include "common.h" /** diff --git a/api/mraa/gpio.hpp b/api/mraa/gpio.hpp index 98693ac..cdcb0ba 100644 --- a/api/mraa/gpio.hpp +++ b/api/mraa/gpio.hpp @@ -28,6 +28,13 @@ #include "types.hpp" #include +#if defined(SWIGJAVA) || defined(JAVACALLBACK) +extern "C" { + void mraa_java_isr_callback(void *args); +} +#endif + + #if defined(SWIGJAVASCRIPT) #if NODE_MODULE_VERSION >= 0x000D #include diff --git a/include/java/mraajni.h b/include/java/mraajni.h new file mode 100644 index 0000000..771d8b4 --- /dev/null +++ b/include/java/mraajni.h @@ -0,0 +1,44 @@ +/* + * Author: Henry bruce + * Copyright (c) 2014 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 + +#ifdef __cplusplus +extern "C" { +#endif + +#include "jni.h" +#include "mraa/types.h" + +void mraa_java_set_jvm(JavaVM* vm); +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); +void mraa_java_delete_global_ref(void* ref); + +#ifdef __cplusplus +} +#endif + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a37b7f0..6e2aa15 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -117,17 +117,6 @@ set (mraa_LIB_GLOB_HEADERS ${PROJECT_SOURCE_DIR}/api/mraa.hpp ) -add_library (mraa ${mraa_LIB_SRCS}) - - -target_link_libraries (mraa ${mraa_LIBS}) - -set_target_properties( - mraa - PROPERTIES - SOVERSION ${mraa_VERSION_MAJOR} - VERSION ${mraa_VERSION_STRING} -) install (FILES ${mraa_LIB_GLOB_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) install (DIRECTORY ${PROJECT_SOURCE_DIR}/api/mraa/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/mraa) @@ -137,7 +126,6 @@ macro (mraa_CREATE_INSTALL_PKGCONFIG generated_file install_location) endmacro (mraa_CREATE_INSTALL_PKGCONFIG) mraa_create_install_pkgconfig (mraa.pc ${CMAKE_INSTALL_LIBDIR}/pkgconfig) -install(TARGETS mraa DESTINATION ${CMAKE_INSTALL_LIBDIR}) if (DOXYGEN_FOUND) set (CMAKE_SWIG_FLAGS -DDOXYGEN=${DOXYGEN_FOUND}) @@ -187,6 +175,15 @@ 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) @@ -198,3 +195,13 @@ if (BUILDSWIG) endif () endif () endif () + +add_library (mraa ${mraa_LIB_SRCS}) +target_link_libraries (mraa ${mraa_LIBS}) +set_target_properties( + mraa + PROPERTIES + SOVERSION ${mraa_VERSION_MAJOR} + VERSION ${mraa_VERSION_STRING} +) +install(TARGETS mraa DESTINATION ${CMAKE_INSTALL_LIBDIR}) diff --git a/src/gpio/gpio.c b/src/gpio/gpio.c index 3b41612..e89666b 100644 --- a/src/gpio/gpio.c +++ b/src/gpio/gpio.c @@ -24,6 +24,9 @@ */ #include "gpio.h" #include "mraa_internal.h" +#if defined(SWIGJAVA) || defined(JAVACALLBACK) +#include "java/mraajni.h" +#endif #include #include @@ -234,36 +237,6 @@ mraa_gpio_wait_interrupt(int fd return MRAA_SUCCESS; } -#if defined(SWIGJAVA) || defined(JAVACALLBACK) -pthread_key_t env_key; - -extern JavaVM *globVM; -static pthread_once_t env_key_init = PTHREAD_ONCE_INIT; - -jmethodID runGlobal; - -static void make_env_key(void) -{ - - JNIEnv *jenv; - (*globVM)->GetEnv(globVM, (void **)&jenv, JNI_VERSION_1_6); - - jclass rcls = (*jenv)->FindClass(jenv, "java/lang/Runnable"); - jmethodID runm = (*jenv)->GetMethodID(jenv, rcls, "run", "()V"); - - runGlobal = (jmethodID)(*jenv)->NewGlobalRef(jenv, (jobject)runm); - - pthread_key_create(&env_key, NULL); -} - -void mraa_java_isr_callback(void* data) -{ - JNIEnv *jenv = (JNIEnv *) pthread_getspecific(env_key); - (*jenv)->CallVoidMethod(jenv, (jobject)data, runGlobal); -} - -#endif - static void* mraa_gpio_interrupt_handler(void* arg) { @@ -296,18 +269,12 @@ mraa_gpio_interrupt_handler(void* arg) dev->isr_value_fp = fp; #if defined(SWIGJAVA) || defined(JAVACALLBACK) - JNIEnv *jenv; if(dev->isr == mraa_java_isr_callback) { - jint err = (*globVM)->AttachCurrentThreadAsDaemon(globVM, (void **)&jenv, NULL); - - if (err != JNI_OK) { - close(dev->isr_value_fp); - dev->isr_value_fp = -1; - return NULL; + if (mraa_java_attach_thread() != MRAA_SUCCESS) { + close(dev->isr_value_fp); + dev->isr_value_fp = -1; + return NULL; } - - pthread_once(&env_key_init, make_env_key); - pthread_setspecific(env_key, jenv); } #endif @@ -403,10 +370,9 @@ mraa_gpio_interrupt_handler(void* arg) dev->isr_value_fp = -1; } #if defined(SWIGJAVA) || defined(JAVACALLBACK) - if(dev->isr == mraa_java_isr_callback) { - (*jenv)->DeleteGlobalRef(jenv, (jobject)dev->isr_args); - (*globVM)->DetachCurrentThread(globVM); + mraa_java_delete_global_ref(dev->isr_args); + mraa_java_detach_thread(); } #endif return NULL; @@ -477,13 +443,10 @@ mraa_gpio_isr(mraa_gpio_context dev, mraa_gpio_edge_t mode, void (*fptr)(void*), dev->isr = fptr; #if defined(SWIGJAVA) || defined(JAVACALLBACK) - JNIEnv *jenv; /* Most UPM sensors use the C API, the global ref must be created here. */ /* The reason for checking the callback function is internal callbacks. */ if (fptr == mraa_java_isr_callback) { - (*globVM)->GetEnv(globVM, (void **)&jenv, JNI_VERSION_1_6); - jobject grunnable = (*jenv)->NewGlobalRef(jenv, (jobject) args); - args = (void *) grunnable; + args = mraa_java_create_global_ref(args); } #endif dev->isr_args = args; diff --git a/src/java/CMakeLists.txt b/src/java/CMakeLists.txt index 33ec6af..c6a2897 100644 --- a/src/java/CMakeLists.txt +++ b/src/java/CMakeLists.txt @@ -1,11 +1,3 @@ -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) @@ -25,8 +17,8 @@ else () set (JAR $ENV{JAVA_HOME_NATIVE}/bin/jar) endif () -swig_add_module (mraajava java mraajava.i ${mraa_LIB_SRCS}) -swig_link_libraries (mraajava ${JAVA_LIBRARIES} ${mraa_LIBS}) +swig_add_module (mraajava java mraajava.i) +swig_link_libraries (mraajava ${JAVA_LIBRARIES} mraa) add_custom_command (TARGET mraajava POST_BUILD diff --git a/src/java/mraajava.i b/src/java/mraajava.i index 9dc7142..25d0a01 100644 --- a/src/java/mraajava.i +++ b/src/java/mraajava.i @@ -65,11 +65,11 @@ class Spi; %include ../mraa.i %wrapper %{ - JavaVM *globVM; + #include "java/mraajni.h" jint JNI_OnLoad(JavaVM *vm, void *reserved) { /* initialize mraa */ - globVM = vm; + mraa_java_set_jvm(vm); mraa_init(); return JNI_VERSION_1_6; } diff --git a/src/java/mraajni.c b/src/java/mraajni.c new file mode 100644 index 0000000..1c09cbb --- /dev/null +++ b/src/java/mraajni.c @@ -0,0 +1,103 @@ +/* + * 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 "java/mraajni.h" + +static pthread_key_t env_key; +static pthread_once_t env_key_init = PTHREAD_ONCE_INIT; +static jmethodID runGlobal; +static JavaVM* globVM = NULL; + + +void +mraa_java_set_jvm(JavaVM* vm) +{ + globVM = vm; +} + +static void +mraa_java_make_env_key(void) +{ + if (globVM != NULL) { + 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); + pthread_key_create(&env_key, NULL); + } +} + +void +mraa_java_isr_callback(void* data) +{ + 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); + if (err == JNI_OK) { + pthread_once(&env_key_init, mraa_java_make_env_key); + pthread_setspecific(env_key, jenv); + return MRAA_SUCCESS; + } + } + return MRAA_ERROR_UNSPECIFIED; +} + +void +mraa_java_detach_thread() +{ + if (globVM != NULL) + (*globVM)->DetachCurrentThread(globVM); +} + +void* +mraa_java_create_global_ref(void* args) +{ + if (globVM != NULL) { + JNIEnv *jenv; + (*globVM)->GetEnv(globVM, (void **)&jenv, JNI_VERSION_1_8); + jobject grunnable = (*jenv)->NewGlobalRef(jenv, (jobject) args); + return (void *)grunnable; + } else + return NULL; +} + +void +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); + } +} +