Move library init/uninit to JNI_OnLoad/JNI_OnUnload

This commit is contained in:
Will Hedgecock 2022-02-18 10:28:38 -06:00
parent 05aae9078a
commit 024c757eab
34 changed files with 241 additions and 212 deletions

View File

@ -2,7 +2,7 @@
* SerialPort_Posix.c
*
* Created on: Feb 25, 2012
* Last Updated on: Feb 16, 2022
* Last Updated on: Feb 18, 2022
* Author: Will Hedgecock
*
* Copyright (C) 2012-2022 Fazecast, Inc.
@ -45,7 +45,6 @@
// Cached class, method, and field IDs
jclass jniErrorClass;
jclass serialCommClass;
jmethodID serialCommConstructor;
jfieldID serialPortFdField;
jfieldID comPortField;
@ -81,6 +80,7 @@ jfieldID eventFlagsField;
// Global list of available serial ports
char portsEnumerated = 0;
char classInitialized = 0;
pthread_mutex_t criticalSection;
serialPortVector serialPorts = { NULL, 0, 0 };
@ -239,6 +239,133 @@ void* eventReadingThread2(void *serialPortPointer)
#endif // #if defined(__linux__)
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved)
{
// Retrieve the JNI environment and class
JNIEnv *env;
jint jniVersion = JNI_VERSION_1_2;
if ((*jvm)->GetEnv(jvm, (void**)&env, jniVersion))
return JNI_ERR;
jclass serialCommClass = (*env)->FindClass(env, "com/fazecast/jSerialComm/SerialPort");
if (!serialCommClass) return JNI_ERR;
jniErrorClass = (*env)->FindClass(env, "java/lang/Exception");
if (!jniErrorClass) return JNI_ERR;
// Cache Java fields as global references
serialCommConstructor = (*env)->GetMethodID(env, serialCommClass, "<init>", "()V");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
serialPortFdField = (*env)->GetFieldID(env, serialCommClass, "portHandle", "J");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
comPortField = (*env)->GetFieldID(env, serialCommClass, "comPort", "Ljava/lang/String;");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
friendlyNameField = (*env)->GetFieldID(env, serialCommClass, "friendlyName", "Ljava/lang/String;");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
portDescriptionField = (*env)->GetFieldID(env, serialCommClass, "portDescription", "Ljava/lang/String;");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
portLocationField = (*env)->GetFieldID(env, serialCommClass, "portLocation", "Ljava/lang/String;");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
eventListenerRunningField = (*env)->GetFieldID(env, serialCommClass, "eventListenerRunning", "Z");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
disableConfigField = (*env)->GetFieldID(env, serialCommClass, "disableConfig", "Z");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
isDtrEnabledField = (*env)->GetFieldID(env, serialCommClass, "isDtrEnabled", "Z");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
isRtsEnabledField = (*env)->GetFieldID(env, serialCommClass, "isRtsEnabled", "Z");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
autoFlushIOBuffersField = (*env)->GetFieldID(env, serialCommClass, "autoFlushIOBuffers", "Z");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
baudRateField = (*env)->GetFieldID(env, serialCommClass, "baudRate", "I");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
dataBitsField = (*env)->GetFieldID(env, serialCommClass, "dataBits", "I");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
stopBitsField = (*env)->GetFieldID(env, serialCommClass, "stopBits", "I");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
parityField = (*env)->GetFieldID(env, serialCommClass, "parity", "I");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
flowControlField = (*env)->GetFieldID(env, serialCommClass, "flowControl", "I");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
sendDeviceQueueSizeField = (*env)->GetFieldID(env, serialCommClass, "sendDeviceQueueSize", "I");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
receiveDeviceQueueSizeField = (*env)->GetFieldID(env, serialCommClass, "receiveDeviceQueueSize", "I");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
disableExclusiveLockField = (*env)->GetFieldID(env, serialCommClass, "disableExclusiveLock", "Z");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
requestElevatedPermissionsField = (*env)->GetFieldID(env, serialCommClass, "requestElevatedPermissions", "Z");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
rs485ModeField = (*env)->GetFieldID(env, serialCommClass, "rs485Mode", "Z");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
rs485ActiveHighField = (*env)->GetFieldID(env, serialCommClass, "rs485ActiveHigh", "Z");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
rs485EnableTerminationField = (*env)->GetFieldID(env, serialCommClass, "rs485EnableTermination", "Z");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
rs485RxDuringTxField = (*env)->GetFieldID(env, serialCommClass, "rs485RxDuringTx", "Z");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
rs485DelayBeforeField = (*env)->GetFieldID(env, serialCommClass, "rs485DelayBefore", "I");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
rs485DelayAfterField = (*env)->GetFieldID(env, serialCommClass, "rs485DelayAfter", "I");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
xonStartCharField = (*env)->GetFieldID(env, serialCommClass, "xonStartChar", "B");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
xoffStopCharField = (*env)->GetFieldID(env, serialCommClass, "xoffStopChar", "B");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
timeoutModeField = (*env)->GetFieldID(env, serialCommClass, "timeoutMode", "I");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
readTimeoutField = (*env)->GetFieldID(env, serialCommClass, "readTimeout", "I");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
writeTimeoutField = (*env)->GetFieldID(env, serialCommClass, "writeTimeout", "I");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
eventFlagsField = (*env)->GetFieldID(env, serialCommClass, "eventFlags", "I");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
// Disable handling of various POSIX signals
sigset_t blockMask;
memset(&blockMask, 0, sizeof(blockMask));
struct sigaction ignoreAction = { 0 };
ignoreAction.sa_handler = SIG_IGN;
ignoreAction.sa_mask = blockMask;
sigaction(SIGIO, &ignoreAction, NULL);
sigaction(SIGHUP, &ignoreAction, NULL);
sigaction(SIGCONT, &ignoreAction, NULL);
sigaction(SIGUSR1, &ignoreAction, NULL);
sigaction(SIGUSR2, &ignoreAction, NULL);
sigaction(SIGTTOU, &ignoreAction, NULL);
sigaction(SIGTTIN, &ignoreAction, NULL);
// Initialize the critical section lock
pthread_mutex_init(&criticalSection, NULL);
classInitialized = 1;
return jniVersion;
}
JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *jvm, void *reserved)
{
// Ensure that the class has not already been uninitialized
if (!classInitialized)
return;
classInitialized = 0;
// Retrieve the JNI environment
JNIEnv *env;
jint jniVersion = JNI_VERSION_1_2;
(*jvm)->GetEnv(jvm, (void**)&env, jniVersion);
// Close all open ports
for (int i = 0; i < serialPorts.length; ++i)
if (serialPorts.ports[i]->handle > 0)
Java_com_fazecast_jSerialComm_SerialPort_closePortNative(env, jniErrorClass, (jlong)(intptr_t)serialPorts.ports[i]);
// Delete the critical section lock
pthread_mutex_destroy(&criticalSection);
}
JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_uninitializeLibrary(JNIEnv *env, jclass serialComm)
{
// Call the JNI Unload function
JavaVM *jvm;
(*env)->GetJavaVM(env, &jvm);
JNI_OnUnload(jvm, NULL);
}
JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommPorts(JNIEnv *env, jclass serialComm)
{
// Mark this entire function as a critical section
@ -248,12 +375,12 @@ JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommP
enumeratePorts();
// Create a Java-based port listing
jobjectArray arrayObject = (*env)->NewObjectArray(env, serialPorts.length, serialCommClass, 0);
jobjectArray arrayObject = (*env)->NewObjectArray(env, serialPorts.length, serialComm, 0);
char stopLooping = checkJniError(env, __LINE__ - 1) ? 1 : 0;
for (int i = 0; !stopLooping && (i < serialPorts.length); ++i)
{
// Create a new SerialComm object containing the enumerated values
jobject serialCommObject = (*env)->NewObject(env, serialCommClass, serialCommConstructor);
jobject serialCommObject = (*env)->NewObject(env, serialComm, serialCommConstructor);
if (checkJniError(env, __LINE__ - 1)) stopLooping = 1;
(*env)->SetObjectField(env, serialCommObject, portDescriptionField, (*env)->NewStringUTF(env, serialPorts.ports[i]->portDescription));
if (checkJniError(env, __LINE__ - 1)) stopLooping = 1;
@ -274,112 +401,6 @@ JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommP
return arrayObject;
}
JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_initializeLibrary(JNIEnv *env, jclass serialComm)
{
// Cache class and method ID as global references
jniErrorClass = (*env)->FindClass(env, "java/lang/Exception");
serialCommClass = (jclass)(*env)->NewGlobalRef(env, serialComm);
if (checkJniError(env, __LINE__ - 1)) return;
serialCommConstructor = (*env)->GetMethodID(env, serialCommClass, "<init>", "()V");
if (checkJniError(env, __LINE__ - 1)) return;
// Cache Java fields as global references
serialPortFdField = (*env)->GetFieldID(env, serialCommClass, "portHandle", "J");
if (checkJniError(env, __LINE__ - 1)) return;
comPortField = (*env)->GetFieldID(env, serialCommClass, "comPort", "Ljava/lang/String;");
if (checkJniError(env, __LINE__ - 1)) return;
friendlyNameField = (*env)->GetFieldID(env, serialCommClass, "friendlyName", "Ljava/lang/String;");
if (checkJniError(env, __LINE__ - 1)) return;
portDescriptionField = (*env)->GetFieldID(env, serialCommClass, "portDescription", "Ljava/lang/String;");
if (checkJniError(env, __LINE__ - 1)) return;
portLocationField = (*env)->GetFieldID(env, serialCommClass, "portLocation", "Ljava/lang/String;");
if (checkJniError(env, __LINE__ - 1)) return;
eventListenerRunningField = (*env)->GetFieldID(env, serialCommClass, "eventListenerRunning", "Z");
if (checkJniError(env, __LINE__ - 1)) return;
disableConfigField = (*env)->GetFieldID(env, serialCommClass, "disableConfig", "Z");
if (checkJniError(env, __LINE__ - 1)) return;
isDtrEnabledField = (*env)->GetFieldID(env, serialCommClass, "isDtrEnabled", "Z");
if (checkJniError(env, __LINE__ - 1)) return;
isRtsEnabledField = (*env)->GetFieldID(env, serialCommClass, "isRtsEnabled", "Z");
if (checkJniError(env, __LINE__ - 1)) return;
autoFlushIOBuffersField = (*env)->GetFieldID(env, serialCommClass, "autoFlushIOBuffers", "Z");
if (checkJniError(env, __LINE__ - 1)) return;
baudRateField = (*env)->GetFieldID(env, serialCommClass, "baudRate", "I");
if (checkJniError(env, __LINE__ - 1)) return;
dataBitsField = (*env)->GetFieldID(env, serialCommClass, "dataBits", "I");
if (checkJniError(env, __LINE__ - 1)) return;
stopBitsField = (*env)->GetFieldID(env, serialCommClass, "stopBits", "I");
if (checkJniError(env, __LINE__ - 1)) return;
parityField = (*env)->GetFieldID(env, serialCommClass, "parity", "I");
if (checkJniError(env, __LINE__ - 1)) return;
flowControlField = (*env)->GetFieldID(env, serialCommClass, "flowControl", "I");
if (checkJniError(env, __LINE__ - 1)) return;
sendDeviceQueueSizeField = (*env)->GetFieldID(env, serialCommClass, "sendDeviceQueueSize", "I");
if (checkJniError(env, __LINE__ - 1)) return;
receiveDeviceQueueSizeField = (*env)->GetFieldID(env, serialCommClass, "receiveDeviceQueueSize", "I");
if (checkJniError(env, __LINE__ - 1)) return;
disableExclusiveLockField = (*env)->GetFieldID(env, serialCommClass, "disableExclusiveLock", "Z");
if (checkJniError(env, __LINE__ - 1)) return;
requestElevatedPermissionsField = (*env)->GetFieldID(env, serialCommClass, "requestElevatedPermissions", "Z");
if (checkJniError(env, __LINE__ - 1)) return;
rs485ModeField = (*env)->GetFieldID(env, serialCommClass, "rs485Mode", "Z");
if (checkJniError(env, __LINE__ - 1)) return;
rs485ActiveHighField = (*env)->GetFieldID(env, serialCommClass, "rs485ActiveHigh", "Z");
if (checkJniError(env, __LINE__ - 1)) return;
rs485EnableTerminationField = (*env)->GetFieldID(env, serialCommClass, "rs485EnableTermination", "Z");
if (checkJniError(env, __LINE__ - 1)) return;
rs485RxDuringTxField = (*env)->GetFieldID(env, serialCommClass, "rs485RxDuringTx", "Z");
if (checkJniError(env, __LINE__ - 1)) return;
rs485DelayBeforeField = (*env)->GetFieldID(env, serialCommClass, "rs485DelayBefore", "I");
if (checkJniError(env, __LINE__ - 1)) return;
rs485DelayAfterField = (*env)->GetFieldID(env, serialCommClass, "rs485DelayAfter", "I");
if (checkJniError(env, __LINE__ - 1)) return;
xonStartCharField = (*env)->GetFieldID(env, serialCommClass, "xonStartChar", "B");
if (checkJniError(env, __LINE__ - 1)) return;
xoffStopCharField = (*env)->GetFieldID(env, serialCommClass, "xoffStopChar", "B");
if (checkJniError(env, __LINE__ - 1)) return;
timeoutModeField = (*env)->GetFieldID(env, serialCommClass, "timeoutMode", "I");
if (checkJniError(env, __LINE__ - 1)) return;
readTimeoutField = (*env)->GetFieldID(env, serialCommClass, "readTimeout", "I");
if (checkJniError(env, __LINE__ - 1)) return;
writeTimeoutField = (*env)->GetFieldID(env, serialCommClass, "writeTimeout", "I");
if (checkJniError(env, __LINE__ - 1)) return;
eventFlagsField = (*env)->GetFieldID(env, serialCommClass, "eventFlags", "I");
if (checkJniError(env, __LINE__ - 1)) return;
// Disable handling of various POSIX signals
sigset_t blockMask;
memset(&blockMask, 0, sizeof(blockMask));
struct sigaction ignoreAction = { 0 };
ignoreAction.sa_handler = SIG_IGN;
ignoreAction.sa_mask = blockMask;
sigaction(SIGIO, &ignoreAction, NULL);
sigaction(SIGHUP, &ignoreAction, NULL);
sigaction(SIGCONT, &ignoreAction, NULL);
sigaction(SIGUSR1, &ignoreAction, NULL);
sigaction(SIGUSR2, &ignoreAction, NULL);
sigaction(SIGTTOU, &ignoreAction, NULL);
sigaction(SIGTTIN, &ignoreAction, NULL);
// Initialize the critical section lock
pthread_mutex_init(&criticalSection, NULL);
}
JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_uninitializeLibrary(JNIEnv *env, jclass serialComm)
{
// Close all open ports
for (int i = 0; i < serialPorts.length; ++i)
if (serialPorts.ports[i]->handle > 0)
Java_com_fazecast_jSerialComm_SerialPort_closePortNative(env, serialComm, (jlong)(intptr_t)serialPorts.ports[i]);
// Delete the cached global reference
(*env)->DeleteGlobalRef(env, serialCommClass);
checkJniError(env, __LINE__ - 1);
// Delete the critical section lock
pthread_mutex_destroy(&criticalSection);
}
JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_retrievePortDetails(JNIEnv *env, jobject obj)
{
// Retrieve the serial port parameter fields

View File

@ -83,14 +83,6 @@ extern "C" {
JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommPorts
(JNIEnv *, jclass);
/*
* Class: com_fazecast_jSerialComm_SerialPort
* Method: initializeLibrary
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_initializeLibrary
(JNIEnv *, jclass);
/*
* Class: com_fazecast_jSerialComm_SerialPort
* Method: uninitializeLibrary

View File

@ -2,7 +2,7 @@
* SerialPort_Windows.c
*
* Created on: Feb 25, 2012
* Last Updated on: Feb 17, 2022
* Last Updated on: Feb 18, 2022
* Author: Will Hedgecock
*
* Copyright (C) 2012-2022 Fazecast, Inc.
@ -44,7 +44,6 @@
// Cached class, method, and field IDs
jclass jniErrorClass;
jclass serialCommClass;
jmethodID serialCommConstructor;
jfieldID serialPortHandleField;
jfieldID comPortField;
@ -80,6 +79,7 @@ typedef int (__stdcall *FT_GetDeviceInfoListFunction)(FT_DEVICE_LIST_INFO_NODE*,
// Global list of available serial ports
char portsEnumerated = 0;
char classInitialized = 0;
CRITICAL_SECTION criticalSection;
serialPortVector serialPorts = { NULL, 0, 0 };
@ -370,6 +370,111 @@ static void enumeratePorts(void)
portsEnumerated = 1;
}
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved)
{
// Retrieve the JNI environment and class
JNIEnv *env;
jint jniVersion = JNI_VERSION_1_2;
if ((*jvm)->GetEnv(jvm, (void**)&env, jniVersion))
return JNI_ERR;
jclass serialCommClass = (*env)->FindClass(env, "com/fazecast/jSerialComm/SerialPort");
if (!serialCommClass) return JNI_ERR;
jniErrorClass = (*env)->FindClass(env, "java/lang/Exception");
if (!jniErrorClass) return JNI_ERR;
// Cache Java fields as global references
serialCommConstructor = (*env)->GetMethodID(env, serialCommClass, "<init>", "()V");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
serialPortHandleField = (*env)->GetFieldID(env, serialCommClass, "portHandle", "J");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
comPortField = (*env)->GetFieldID(env, serialCommClass, "comPort", "Ljava/lang/String;");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
friendlyNameField = (*env)->GetFieldID(env, serialCommClass, "friendlyName", "Ljava/lang/String;");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
portDescriptionField = (*env)->GetFieldID(env, serialCommClass, "portDescription", "Ljava/lang/String;");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
portLocationField = (*env)->GetFieldID(env, serialCommClass, "portLocation", "Ljava/lang/String;");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
eventListenerRunningField = (*env)->GetFieldID(env, serialCommClass, "eventListenerRunning", "Z");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
disableConfigField = (*env)->GetFieldID(env, serialCommClass, "disableConfig", "Z");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
isDtrEnabledField = (*env)->GetFieldID(env, serialCommClass, "isDtrEnabled", "Z");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
isRtsEnabledField = (*env)->GetFieldID(env, serialCommClass, "isRtsEnabled", "Z");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
autoFlushIOBuffersField = (*env)->GetFieldID(env, serialCommClass, "autoFlushIOBuffers", "Z");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
baudRateField = (*env)->GetFieldID(env, serialCommClass, "baudRate", "I");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
dataBitsField = (*env)->GetFieldID(env, serialCommClass, "dataBits", "I");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
stopBitsField = (*env)->GetFieldID(env, serialCommClass, "stopBits", "I");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
parityField = (*env)->GetFieldID(env, serialCommClass, "parity", "I");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
flowControlField = (*env)->GetFieldID(env, serialCommClass, "flowControl", "I");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
sendDeviceQueueSizeField = (*env)->GetFieldID(env, serialCommClass, "sendDeviceQueueSize", "I");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
receiveDeviceQueueSizeField = (*env)->GetFieldID(env, serialCommClass, "receiveDeviceQueueSize", "I");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
requestElevatedPermissionsField = (*env)->GetFieldID(env, serialCommClass, "requestElevatedPermissions", "Z");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
rs485ModeField = (*env)->GetFieldID(env, serialCommClass, "rs485Mode", "Z");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
rs485DelayBeforeField = (*env)->GetFieldID(env, serialCommClass, "rs485DelayBefore", "I");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
rs485DelayAfterField = (*env)->GetFieldID(env, serialCommClass, "rs485DelayAfter", "I");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
xonStartCharField = (*env)->GetFieldID(env, serialCommClass, "xonStartChar", "B");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
xoffStopCharField = (*env)->GetFieldID(env, serialCommClass, "xoffStopChar", "B");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
timeoutModeField = (*env)->GetFieldID(env, serialCommClass, "timeoutMode", "I");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
readTimeoutField = (*env)->GetFieldID(env, serialCommClass, "readTimeout", "I");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
writeTimeoutField = (*env)->GetFieldID(env, serialCommClass, "writeTimeout", "I");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
eventFlagsField = (*env)->GetFieldID(env, serialCommClass, "eventFlags", "I");
if (checkJniError(env, __LINE__ - 1)) return JNI_ERR;
// Initialize the critical section lock
InitializeCriticalSection(&criticalSection);
classInitialized = 1;
return jniVersion;
}
JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *jvm, void *reserved)
{
// Ensure that the class has not already been uninitialized
if (!classInitialized)
return;
classInitialized = 0;
// Retrieve the JNI environment
JNIEnv *env;
jint jniVersion = JNI_VERSION_1_2;
(*jvm)->GetEnv(jvm, (void**)&env, jniVersion);
// Close all open ports
for (int i = 0; i < serialPorts.length; ++i)
if (serialPorts.ports[i]->handle != INVALID_HANDLE_VALUE)
Java_com_fazecast_jSerialComm_SerialPort_closePortNative(env, jniErrorClass, (jlong)(intptr_t)serialPorts.ports[i]);
// Delete the critical section lock
DeleteCriticalSection(&criticalSection);
}
JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_uninitializeLibrary(JNIEnv *env, jclass serialComm)
{
// Call the JNI Unload function
JavaVM *jvm;
(*env)->GetJavaVM(env, &jvm);
JNI_OnUnload(jvm, NULL);
}
JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommPorts(JNIEnv *env, jclass serialComm)
{
// Mark this entire function as a critical section
@ -379,12 +484,12 @@ JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommP
enumeratePorts();
// Get relevant SerialComm methods and fill in com port array
jobjectArray arrayObject = (*env)->NewObjectArray(env, serialPorts.length, serialCommClass, 0);
jobjectArray arrayObject = (*env)->NewObjectArray(env, serialPorts.length, serialComm, 0);
char stopLooping = checkJniError(env, __LINE__ - 1) ? 1 : 0;
for (int i = 0; !stopLooping && (i < serialPorts.length); ++i)
{
// Create new SerialComm object containing the enumerated values
jobject serialCommObject = (*env)->NewObject(env, serialCommClass, serialCommConstructor);
jobject serialCommObject = (*env)->NewObject(env, serialComm, serialCommConstructor);
if (checkJniError(env, __LINE__ - 1)) stopLooping = 1;
(*env)->SetObjectField(env, serialCommObject, comPortField, (*env)->NewString(env, (jchar*)serialPorts.ports[i]->portPath, wcslen(serialPorts.ports[i]->portPath)));
if (checkJniError(env, __LINE__ - 1)) stopLooping = 1;
@ -405,90 +510,6 @@ JNIEXPORT jobjectArray JNICALL Java_com_fazecast_jSerialComm_SerialPort_getCommP
return arrayObject;
}
JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_initializeLibrary(JNIEnv *env, jclass serialComm)
{
// Cache class and method ID as global references
jniErrorClass = (*env)->FindClass(env, "java/lang/Exception");
serialCommClass = (jclass)(*env)->NewGlobalRef(env, serialComm);
if (checkJniError(env, __LINE__ - 1)) return;
serialCommConstructor = (*env)->GetMethodID(env, serialCommClass, "<init>", "()V");
if (checkJniError(env, __LINE__ - 1)) return;
// Cache Java fields as global references
serialPortHandleField = (*env)->GetFieldID(env, serialCommClass, "portHandle", "J");
if (checkJniError(env, __LINE__ - 1)) return;
comPortField = (*env)->GetFieldID(env, serialCommClass, "comPort", "Ljava/lang/String;");
if (checkJniError(env, __LINE__ - 1)) return;
friendlyNameField = (*env)->GetFieldID(env, serialCommClass, "friendlyName", "Ljava/lang/String;");
if (checkJniError(env, __LINE__ - 1)) return;
portDescriptionField = (*env)->GetFieldID(env, serialCommClass, "portDescription", "Ljava/lang/String;");
if (checkJniError(env, __LINE__ - 1)) return;
portLocationField = (*env)->GetFieldID(env, serialCommClass, "portLocation", "Ljava/lang/String;");
if (checkJniError(env, __LINE__ - 1)) return;
eventListenerRunningField = (*env)->GetFieldID(env, serialCommClass, "eventListenerRunning", "Z");
if (checkJniError(env, __LINE__ - 1)) return;
disableConfigField = (*env)->GetFieldID(env, serialCommClass, "disableConfig", "Z");
if (checkJniError(env, __LINE__ - 1)) return;
isDtrEnabledField = (*env)->GetFieldID(env, serialCommClass, "isDtrEnabled", "Z");
if (checkJniError(env, __LINE__ - 1)) return;
isRtsEnabledField = (*env)->GetFieldID(env, serialCommClass, "isRtsEnabled", "Z");
if (checkJniError(env, __LINE__ - 1)) return;
autoFlushIOBuffersField = (*env)->GetFieldID(env, serialCommClass, "autoFlushIOBuffers", "Z");
if (checkJniError(env, __LINE__ - 1)) return;
baudRateField = (*env)->GetFieldID(env, serialCommClass, "baudRate", "I");
if (checkJniError(env, __LINE__ - 1)) return;
dataBitsField = (*env)->GetFieldID(env, serialCommClass, "dataBits", "I");
if (checkJniError(env, __LINE__ - 1)) return;
stopBitsField = (*env)->GetFieldID(env, serialCommClass, "stopBits", "I");
if (checkJniError(env, __LINE__ - 1)) return;
parityField = (*env)->GetFieldID(env, serialCommClass, "parity", "I");
if (checkJniError(env, __LINE__ - 1)) return;
flowControlField = (*env)->GetFieldID(env, serialCommClass, "flowControl", "I");
if (checkJniError(env, __LINE__ - 1)) return;
sendDeviceQueueSizeField = (*env)->GetFieldID(env, serialCommClass, "sendDeviceQueueSize", "I");
if (checkJniError(env, __LINE__ - 1)) return;
receiveDeviceQueueSizeField = (*env)->GetFieldID(env, serialCommClass, "receiveDeviceQueueSize", "I");
if (checkJniError(env, __LINE__ - 1)) return;
requestElevatedPermissionsField = (*env)->GetFieldID(env, serialCommClass, "requestElevatedPermissions", "Z");
if (checkJniError(env, __LINE__ - 1)) return;
rs485ModeField = (*env)->GetFieldID(env, serialCommClass, "rs485Mode", "Z");
if (checkJniError(env, __LINE__ - 1)) return;
rs485DelayBeforeField = (*env)->GetFieldID(env, serialCommClass, "rs485DelayBefore", "I");
if (checkJniError(env, __LINE__ - 1)) return;
rs485DelayAfterField = (*env)->GetFieldID(env, serialCommClass, "rs485DelayAfter", "I");
if (checkJniError(env, __LINE__ - 1)) return;
xonStartCharField = (*env)->GetFieldID(env, serialCommClass, "xonStartChar", "B");
if (checkJniError(env, __LINE__ - 1)) return;
xoffStopCharField = (*env)->GetFieldID(env, serialCommClass, "xoffStopChar", "B");
if (checkJniError(env, __LINE__ - 1)) return;
timeoutModeField = (*env)->GetFieldID(env, serialCommClass, "timeoutMode", "I");
if (checkJniError(env, __LINE__ - 1)) return;
readTimeoutField = (*env)->GetFieldID(env, serialCommClass, "readTimeout", "I");
if (checkJniError(env, __LINE__ - 1)) return;
writeTimeoutField = (*env)->GetFieldID(env, serialCommClass, "writeTimeout", "I");
if (checkJniError(env, __LINE__ - 1)) return;
eventFlagsField = (*env)->GetFieldID(env, serialCommClass, "eventFlags", "I");
if (checkJniError(env, __LINE__ - 1)) return;
// Initialize the critical section lock
InitializeCriticalSection(&criticalSection);
}
JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_uninitializeLibrary(JNIEnv *env, jclass serialComm)
{
// Close all open ports
for (int i = 0; i < serialPorts.length; ++i)
if (serialPorts.ports[i]->handle != INVALID_HANDLE_VALUE)
Java_com_fazecast_jSerialComm_SerialPort_closePortNative(env, serialComm, (jlong)(intptr_t)serialPorts.ports[i]);
// Delete the cached global reference
(*env)->DeleteGlobalRef(env, serialCommClass);
checkJniError(env, __LINE__ - 1);
// Delete the critical section lock
DeleteCriticalSection(&criticalSection);
}
JNIEXPORT void JNICALL Java_com_fazecast_jSerialComm_SerialPort_retrievePortDetails(JNIEnv *env, jobject obj)
{
// Retrieve the serial port parameter fields

View File

@ -396,16 +396,12 @@ public final class SerialPort
else
backupFileContents.close();
}
// Initialize native library
if (libraryLoaded)
initializeLibrary();
}
}
}
catch (Exception e) { e.printStackTrace(); }
// Add a shutdown hook to ensure all ports get closed
// Add a shutdown hook to ensure that all ports get closed
Runtime.getRuntime().addShutdownHook(new Thread()
{
public void run()
@ -765,7 +761,6 @@ public final class SerialPort
public final synchronized int getLastErrorCode() { return getLastErrorCode(portHandle); }
// Serial Port Setup Methods
private static native void initializeLibrary(); // Initializes the JNI code
private static native void uninitializeLibrary(); // Un-initializes the JNI code
private final native void retrievePortDetails(); // Retrieves port descriptions, names, and details
private final native long openPortNative(); // Opens serial port