Simplify JNI interfaces.

These changes both simplify the Java code and improve performance across the
JNI boundary.

This also fixes the AnalogCrossConnectTest by adding delays to
setInterruptHigh() and setInterruptLow() to ensure the change in voltage has
time to propagate and extends the timeouts in AbstractInterruptTest.

Detailed changes:

Hoisted status checks to C.  This avoids the need to create direct byte
buffers (expensive) and significantly simplifies the Java code.  The C code
now directly generates the exception or reports the error to the DS.

The JVM pointer is now a global across the JNI, initialized by the OnLoad
function, avoiding the need for some of the class-specific initializers to
get this pointer for callbacks.

Opaque pointers (such as ports) are now passed as long values rather than
with a ByteBuffer wrapper.

Added extern "C" to source files.  This allows earlier detection of JNI
definition mismatches to the Java source headers.

Changed JNI signatures to more closely match HAL signatures (in particular,
boolean is now universally used instead of byte for HAL bool, which cleans
up mapping back and forth to 1/0 from true/false).

Change-Id: I4ea0032cabb0871cd74106a3a70d947258c29d2d
This commit is contained in:
Peter Johnson
2015-11-01 09:11:52 -08:00
committed by Brad Miller (WPI)
parent 927400a43c
commit 7023013c4b
69 changed files with 2232 additions and 3118 deletions

View File

@@ -1,10 +1,13 @@
#include "HALUtil.h"
#include <jni.h>
#include <assert.h>
#include "Log.hpp"
#include "edu_wpi_first_wpilibj_hal_HALUtil.h"
#include "FRC_NetworkCommunication/CANSessionMux.h"
#include "HAL/HAL.hpp"
#include "errno.h"
#include <string.h>
#include <string>
// set the logging level
TLogLevel halUtilLogLevel = logWARNING;
@@ -13,174 +16,430 @@ TLogLevel halUtilLogLevel = logWARNING;
if (level > halUtilLogLevel) ; \
else Log().Get(level)
#define kRioStatusOffset -63000
#define kRioStatusSuccess 0
#define kRIOStatusBufferInvalidSize (kRioStatusOffset - 80)
#define kRIOStatusOperationTimedOut -52007
#define kRIOStatusFeatureNotSupported (kRioStatusOffset - 193)
#define kRIOStatusResourceNotInitialized -52010
JavaVM *jvm = nullptr;
static jclass throwableCls = nullptr;
static jclass stackTraceElementCls = nullptr;
static jclass runtimeExCls = nullptr;
static jclass illegalArgExCls = nullptr;
static jclass boundaryExCls = nullptr;
static jclass canInvalidBufferExCls = nullptr;
static jclass canMessageNotFoundExCls = nullptr;
static jclass canMessageNotAllowedExCls = nullptr;
static jclass canNotInitializedExCls = nullptr;
static jclass uncleanStatusExCls = nullptr;
static void GetStackTrace(JNIEnv *env, std::string& res) {
// create a throwable
static jmethodID constructorId = nullptr;
if (!constructorId)
constructorId = env->GetMethodID(throwableCls, "<init>", "()V");
jobject throwable = env->NewObject(throwableCls, constructorId);
// retrieve information from the exception.
// get method id
// getStackTrace returns an array of StackTraceElement
static jmethodID getStackTraceId = nullptr;
if (!getStackTraceId)
getStackTraceId = env->GetMethodID(throwableCls, "getStackTrace",
"()[Ljava/lang/StackTraceElement;");
// call getStackTrace
jobjectArray stackTrace =
(jobjectArray)env->CallObjectMethod(throwable, getStackTraceId);
if (!stackTrace) return;
// get length of the array
jsize stackTraceLength = env->GetArrayLength(stackTrace);
// get toString methodId of StackTraceElement class
static jmethodID toStringId = nullptr;
if (!toStringId)
toStringId = env->GetMethodID(stackTraceElementCls, "toString",
"()Ljava/lang/String;");
for (jsize i = 0; i < stackTraceLength; i++) {
// add the result of toString method of each element in the result
jobject curStackTraceElement = env->GetObjectArrayElement(stackTrace, i);
// call to string on the object
jstring stackElementString =
(jstring)env->CallObjectMethod(curStackTraceElement, toStringId);
if (!stackElementString) {
env->DeleteLocalRef(stackTrace);
env->DeleteLocalRef(curStackTraceElement);
return;
}
// add a line to res
//res += " at ";
const char *tmp = env->GetStringUTFChars(stackElementString, nullptr);
res += tmp;
res += '\n';
env->ReleaseStringUTFChars(stackElementString, tmp);
env->DeleteLocalRef(curStackTraceElement);
env->DeleteLocalRef(stackElementString);
}
// release java resources
env->DeleteLocalRef(stackTrace);
}
void ReportError(JNIEnv *env, int32_t status, bool do_throw) {
if (status == 0) return;
const char *message = getHALErrorMessage(status);
if (do_throw && status < 0) {
char *buf = new char[strlen(message) + 30];
sprintf(buf, " Code: %d. %s", status, message);
env->ThrowNew(runtimeExCls, buf);
delete[] buf;
} else {
std::string fullmsg = message;
fullmsg += " at ";
GetStackTrace(env, fullmsg);
fprintf(stderr, "%s\n", fullmsg.c_str());
HALControlWord controlWord;
HALGetControlWord(&controlWord);
if (controlWord.dsAttached)
HALSetErrorData(fullmsg.c_str(), fullmsg.size(), 0);
}
}
void ReportCANError(JNIEnv *env, int32_t status, int message_id) {
if (status >= 0) return;
switch (status) {
case kRioStatusSuccess:
// Everything is ok... don't throw.
break;
case ERR_CANSessionMux_InvalidBuffer:
case kRIOStatusBufferInvalidSize: {
static jmethodID invalidBufConstruct = nullptr;
if (!invalidBufConstruct)
invalidBufConstruct =
env->GetMethodID(canInvalidBufferExCls, "<init>", "()V");
jobject exception =
env->NewObject(canInvalidBufferExCls, invalidBufConstruct);
env->Throw(static_cast<jthrowable>(exception));
break;
}
case ERR_CANSessionMux_MessageNotFound:
case kRIOStatusOperationTimedOut: {
static jmethodID messageNotFoundConstruct = nullptr;
if (!messageNotFoundConstruct)
messageNotFoundConstruct =
env->GetMethodID(canMessageNotFoundExCls, "<init>", "()V");
jobject exception =
env->NewObject(canMessageNotFoundExCls, messageNotFoundConstruct);
env->Throw(static_cast<jthrowable>(exception));
break;
}
case ERR_CANSessionMux_NotAllowed:
case kRIOStatusFeatureNotSupported: {
char buf[100];
sprintf(buf, "MessageID = %d", message_id);
env->ThrowNew(canMessageNotAllowedExCls, buf);
break;
}
case ERR_CANSessionMux_NotInitialized:
case kRIOStatusResourceNotInitialized: {
static jmethodID notInitConstruct = nullptr;
if (!notInitConstruct)
notInitConstruct =
env->GetMethodID(canNotInitializedExCls, "<init>", "()V");
jobject exception =
env->NewObject(canNotInitializedExCls, notInitConstruct);
env->Throw(static_cast<jthrowable>(exception));
break;
}
default: {
char buf[100];
sprintf(buf, "Fatal status code detected: %d", status);
env->ThrowNew(uncleanStatusExCls, buf);
break;
}
}
}
void ThrowIllegalArgumentException(JNIEnv *env, const char *msg) {
env->ThrowNew(illegalArgExCls, msg);
}
void ThrowBoundaryException(JNIEnv *env, double value, double lower,
double upper) {
static jmethodID getMessage = nullptr;
if (!getMessage)
getMessage = env->GetStaticMethodID(boundaryExCls, "getMessage",
"(DDD)Ljava/lang/String;");
static jmethodID constructor = nullptr;
if (!constructor)
constructor =
env->GetMethodID(boundaryExCls, "<init>", "(Ljava/lang/String;)V");
jobject msg =
env->CallStaticObjectMethod(boundaryExCls, getMessage, (jdouble)value,
(jdouble)lower, (jdouble)upper);
jobject ex = env->NewObject(boundaryExCls, constructor, msg);
env->Throw(static_cast<jthrowable>(ex));
}
extern "C" {
//
// indicate JNI version support desired
// indicate JNI version support desired and load classes
//
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
{
jvm = vm;
// set our logging level
Log::ReportingLevel() = logDEBUG;
JNIEnv *env;
if (vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6) != JNI_OK)
return JNI_ERR;
// Cache references to classes
jclass local;
local = env->FindClass("java/lang/Throwable");
if (!local) return JNI_ERR;
throwableCls = static_cast<jclass>(env->NewGlobalRef(local));
if (!throwableCls) return JNI_ERR;
env->DeleteLocalRef(local);
local = env->FindClass("java/lang/StackTraceElement");
if (!local) return JNI_ERR;
stackTraceElementCls = static_cast<jclass>(env->NewGlobalRef(local));
if (!stackTraceElementCls) return JNI_ERR;
env->DeleteLocalRef(local);
local = env->FindClass("java/lang/RuntimeException");
if (!local) return JNI_ERR;
runtimeExCls = static_cast<jclass>(env->NewGlobalRef(local));
if (!runtimeExCls) return JNI_ERR;
env->DeleteLocalRef(local);
local = env->FindClass("java/lang/IllegalArgumentException");
if (!local) return JNI_ERR;
illegalArgExCls = static_cast<jclass>(env->NewGlobalRef(local));
if (!illegalArgExCls) return JNI_ERR;
env->DeleteLocalRef(local);
local = env->FindClass("edu/wpi/first/wpilibj/util/BoundaryException");
if (!local) return JNI_ERR;
boundaryExCls = static_cast<jclass>(env->NewGlobalRef(local));
if (!boundaryExCls) return JNI_ERR;
env->DeleteLocalRef(local);
local = env->FindClass("edu/wpi/first/wpilibj/can/CANInvalidBufferException");
if (!local) return JNI_ERR;
canInvalidBufferExCls = static_cast<jclass>(env->NewGlobalRef(local));
if (!canInvalidBufferExCls) return JNI_ERR;
env->DeleteLocalRef(local);
local =
env->FindClass("edu/wpi/first/wpilibj/can/CANMessageNotFoundException");
if (!local) return JNI_ERR;
canMessageNotFoundExCls = static_cast<jclass>(env->NewGlobalRef(local));
if (!canMessageNotFoundExCls) return JNI_ERR;
env->DeleteLocalRef(local);
local =
env->FindClass("edu/wpi/first/wpilibj/can/CANMessageNotAllowedException");
if (!local) return JNI_ERR;
canMessageNotAllowedExCls = static_cast<jclass>(env->NewGlobalRef(local));
if (!canMessageNotAllowedExCls) return JNI_ERR;
env->DeleteLocalRef(local);
local =
env->FindClass("edu/wpi/first/wpilibj/can/CANNotInitializedException");
if (!local) return JNI_ERR;
canNotInitializedExCls = static_cast<jclass>(env->NewGlobalRef(local));
if (!canNotInitializedExCls) return JNI_ERR;
env->DeleteLocalRef(local);
local = env->FindClass("edu/wpi/first/wpilibj/util/UncleanStatusException");
if (!local) return JNI_ERR;
uncleanStatusExCls = static_cast<jclass>(env->NewGlobalRef(local));
if (!uncleanStatusExCls) return JNI_ERR;
env->DeleteLocalRef(local);
return JNI_VERSION_1_6;
}
JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved)
{
JNIEnv *env;
if (vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6) != JNI_OK)
return;
// Delete global references
if (throwableCls) env->DeleteGlobalRef(throwableCls);
if (stackTraceElementCls) env->DeleteGlobalRef(stackTraceElementCls);
if (runtimeExCls) env->DeleteGlobalRef(runtimeExCls);
if (illegalArgExCls) env->DeleteGlobalRef(illegalArgExCls);
if (boundaryExCls) env->DeleteGlobalRef(boundaryExCls);
if (canInvalidBufferExCls) env->DeleteGlobalRef(canInvalidBufferExCls);
if (canMessageNotFoundExCls) env->DeleteGlobalRef(canMessageNotFoundExCls);
if (canMessageNotAllowedExCls) env->DeleteGlobalRef(canMessageNotAllowedExCls);
if (canNotInitializedExCls) env->DeleteGlobalRef(canNotInitializedExCls);
if (uncleanStatusExCls) env->DeleteGlobalRef(uncleanStatusExCls);
jvm = nullptr;
}
/*
* Class: edu_wpi_first_wpilibj_hal_HALUtil
* Method: initializeMutex
* Signature: (I)Ljava/nio/ByteBuffer;
* Signature: (I)J
*/
JNIEXPORT jobject JNICALL Java_edu_wpi_first_wpilibj_hal_HALUtil_initializeMutexNormal
(JNIEnv * env, jclass)
JNIEXPORT jlong JNICALL Java_edu_wpi_first_wpilibj_hal_HALUtil_initializeMutexNormal
(JNIEnv * env, jclass)
{
HALUTIL_LOG(logDEBUG) << "Calling HALUtil initializeMutex";
MUTEX_ID mutexPtr = (MUTEX_ID)new unsigned char[sizeof(MUTEX_ID)];
mutexPtr = initializeMutexNormal();
HALUTIL_LOG(logDEBUG) << "Mutex Ptr = " << mutexPtr;
return env->NewDirectByteBuffer(mutexPtr, sizeof(MUTEX_ID));
MUTEX_ID mutex = initializeMutexNormal();
HALUTIL_LOG(logDEBUG) << "Mutex Ptr = " << mutex;
return (jlong)mutex;
}
/*
* Class: edu_wpi_first_wpilibj_hal_HALUtil
* Method: deleteMutex
* Signature: (Ljava/nio/ByteBuffer;)V
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_HALUtil_deleteMutex
(JNIEnv * env, jclass, jobject id )
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_HALUtil_deleteMutex
(JNIEnv * env, jclass, jlong id )
{
HALUTIL_LOG(logDEBUG) << "Calling HALUtil deleteMutex";
MUTEX_ID javaId = (MUTEX_ID)env->GetDirectBufferAddress(id);
HALUTIL_LOG(logDEBUG) << "Mutex Ptr = " << javaId;
deleteMutex( javaId );
delete[] javaId;
HALUTIL_LOG(logDEBUG) << "Mutex Ptr = " << (MUTEX_ID)id;
deleteMutex((MUTEX_ID)id);
}
/*
* Class: edu_wpi_first_wpilibj_hal_HALUtil
* Method: takeMutex
* Signature: (Ljava/nio/ByteBuffer;I)B
* Signature: (JI)V
*/
JNIEXPORT jbyte JNICALL Java_edu_wpi_first_wpilibj_hal_HALUtil_takeMutex
(JNIEnv * env, jclass, jobject id)
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_HALUtil_takeMutex
(JNIEnv * env, jclass, jlong id)
{
//HALUTIL_LOG(logDEBUG) << "Calling HALUtil takeMutex";
MUTEX_ID javaId = (MUTEX_ID)env->GetDirectBufferAddress(id);
//HALUTIL_LOG(logDEBUG) << "Mutex Ptr = " << *javaId;
takeMutex(javaId);
//HALUTIL_LOG(logDEBUG) << "Take Result = " << (void*)returnValue;
return 0;
//HALUTIL_LOG(logDEBUG) << "Mutex Ptr = " << (MUTEX_ID)id;
takeMutex((MUTEX_ID)id);
}
/*
* Class: edu_wpi_first_wpilibj_hal_HALUtil
* Method: initializeMultiWait
* Signature: ()Ljava/nio/ByteBuffer;
* Signature: ()J
*/
JNIEXPORT jobject JNICALL Java_edu_wpi_first_wpilibj_hal_HALUtil_initializeMultiWait
(JNIEnv * env, jclass)
JNIEXPORT jlong JNICALL Java_edu_wpi_first_wpilibj_hal_HALUtil_initializeMultiWait
(JNIEnv * env, jclass)
{
HALUTIL_LOG(logDEBUG) << "Calling HALUtil initializeMultiWait";
MULTIWAIT_ID multiWaitPtr = (MULTIWAIT_ID)new unsigned char[4];
multiWaitPtr = initializeMultiWait();
HALUTIL_LOG(logDEBUG) << "MultiWait Ptr = " << multiWaitPtr;
return env->NewDirectByteBuffer( multiWaitPtr, 4);
MULTIWAIT_ID multiWait = initializeMultiWait();
HALUTIL_LOG(logDEBUG) << "MultiWait Ptr = " << multiWait;
return (jlong)multiWait;
}
/*
* Class: edu_wpi_first_wpilibj_hal_HALUtil
* Method: deleteMultiWait
* Signature: (Ljava/nio/ByteBuffer;)V
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_HALUtil_deleteMultiWait
(JNIEnv * env, jclass, jobject id)
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_HALUtil_deleteMultiWait
(JNIEnv * env, jclass, jlong id)
{
HALUTIL_LOG(logDEBUG) << "Calling HALUtil deleteMultiWait";
MULTIWAIT_ID javaId = (MULTIWAIT_ID)env->GetDirectBufferAddress(id);
HALUTIL_LOG(logDEBUG) << "MultiWait Ptr = " << javaId;
deleteMultiWait( javaId );
HALUTIL_LOG(logDEBUG) << "MultiWait Ptr = " << (MULTIWAIT_ID)id;
deleteMultiWait((MULTIWAIT_ID)id);
}
/*
* Class: edu_wpi_first_wpilibj_hal_HALUtil
* Method: takeMultiWait
* Signature: (Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;I)B
* Signature: (JJ)V
*/
JNIEXPORT jbyte JNICALL Java_edu_wpi_first_wpilibj_hal_HALUtil_takeMultiWait
(JNIEnv * env, jclass, jobject multiWaitId, jobject mutexId)
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_HALUtil_takeMultiWait
(JNIEnv * env, jclass, jlong multiWaitId, jlong mutexId)
{
MULTIWAIT_ID javaMultiWaitId = (MULTIWAIT_ID)env->GetDirectBufferAddress(multiWaitId);
MUTEX_ID javaMutexId = (MUTEX_ID)env->GetDirectBufferAddress(mutexId);
takeMultiWait(javaMultiWaitId, javaMutexId);
return 0;
takeMultiWait((MULTIWAIT_ID)multiWaitId, (MUTEX_ID)mutexId);
}
/*
* Class: edu_wpi_first_wpilibj_hal_HALUtil
* Method: getFPGAVersion
* Signature: (Ljava/nio/IntBuffer;)S
* Signature: ()S
*/
JNIEXPORT jshort JNICALL Java_edu_wpi_first_wpilibj_hal_HALUtil_getFPGAVersion
(JNIEnv * env, jclass, jobject status)
JNIEXPORT jshort JNICALL Java_edu_wpi_first_wpilibj_hal_HALUtil_getFPGAVersion
(JNIEnv * env, jclass)
{
HALUTIL_LOG(logDEBUG) << "Calling HALUtil getFPGAVersion";
jint * statusPtr = (jint*)env->GetDirectBufferAddress(status);
*statusPtr = 0;
jshort returnValue = getFPGAVersion( statusPtr );
HALUTIL_LOG(logDEBUG) << "Status = " << *statusPtr;
int32_t status = 0;
jshort returnValue = getFPGAVersion(&status);
HALUTIL_LOG(logDEBUG) << "Status = " << status;
HALUTIL_LOG(logDEBUG) << "FPGAVersion = " << returnValue;
CheckStatus(env, status);
return returnValue;
}
/*
* Class: edu_wpi_first_wpilibj_hal_HALUtil
* Method: getFPGARevision
* Signature: (Ljava/nio/IntBuffer;)I
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_HALUtil_getFPGARevision
(JNIEnv * env, jclass, jobject status)
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_HALUtil_getFPGARevision
(JNIEnv * env, jclass)
{
HALUTIL_LOG(logDEBUG) << "Calling HALUtil getFPGARevision";
jint * statusPtr = (jint*)env->GetDirectBufferAddress(status);
*statusPtr = 0;
jint returnValue = getFPGARevision( statusPtr );
HALUTIL_LOG(logDEBUG) << "Status = " << *statusPtr;
int32_t status = 0;
jint returnValue = getFPGARevision(&status);
HALUTIL_LOG(logDEBUG) << "Status = " << status;
HALUTIL_LOG(logDEBUG) << "FPGARevision = " << returnValue;
CheckStatus(env, status);
return returnValue;
}
/*
* Class: edu_wpi_first_wpilibj_hal_HALUtil
* Method: getFPGATime
* Signature: (Ljava/nio/IntBuffer;)I
* Signature: ()J
*/
JNIEXPORT jlong JNICALL Java_edu_wpi_first_wpilibj_hal_HALUtil_getFPGATime
(JNIEnv * env, jclass, jobject status)
JNIEXPORT jlong JNICALL Java_edu_wpi_first_wpilibj_hal_HALUtil_getFPGATime
(JNIEnv * env, jclass)
{
//HALUTIL_LOG(logDEBUG) << "Calling HALUtil getFPGATime";
jint * statusPtr = (jint*)env->GetDirectBufferAddress(status);
*statusPtr = 0;
jlong returnValue = getFPGATime( statusPtr );
//HALUTIL_LOG(logDEBUG) << "Status = " << *statusPtr;
int32_t status = 0;
jlong returnValue = getFPGATime(&status);
//HALUTIL_LOG(logDEBUG) << "Status = " << status;
//HALUTIL_LOG(logDEBUG) << "FPGATime = " << returnValue;
CheckStatus(env, status);
return returnValue;
}
/*
* Class: edu_wpi_first_wpilibj_hal_HALUtil
* Method: getFPGAButton
* Signature: (Ljava/nio/IntBuffer;)I
* Signature: ()I
*/
JNIEXPORT jboolean JNICALL Java_edu_wpi_first_wpilibj_hal_HALUtil_getFPGAButton
(JNIEnv * env, jclass, jobject status)
JNIEXPORT jboolean JNICALL Java_edu_wpi_first_wpilibj_hal_HALUtil_getFPGAButton
(JNIEnv * env, jclass)
{
//HALUTIL_LOG(logDEBUG) << "Calling HALUtil getFPGATime";
jint * statusPtr = (jint*)env->GetDirectBufferAddress(status);
*statusPtr = 0;
jboolean returnValue = getFPGAButton( statusPtr );
//HALUTIL_LOG(logDEBUG) << "Status = " << *statusPtr;
int32_t status = 0;
jboolean returnValue = getFPGAButton(&status);
//HALUTIL_LOG(logDEBUG) << "Status = " << status;
//HALUTIL_LOG(logDEBUG) << "FPGATime = " << returnValue;
CheckStatus(env, status);
return returnValue;
}
/*
@@ -188,8 +447,8 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
* Method: getHALErrorMessage
* Signature: (I)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_edu_wpi_first_wpilibj_hal_HALUtil_getHALErrorMessage
(JNIEnv * paramEnv, jclass, jint paramId)
JNIEXPORT jstring JNICALL Java_edu_wpi_first_wpilibj_hal_HALUtil_getHALErrorMessage
(JNIEnv * paramEnv, jclass, jint paramId)
{
const char * msg = getHALErrorMessage(paramId);
HALUTIL_LOG(logDEBUG) << "Calling HALUtil getHALErrorMessage id=" << paramId << " msg=" << msg;
@@ -201,8 +460,8 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
* Method: getHALErrno
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_HALUtil_getHALErrno
(JNIEnv *, jclass)
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_HALUtil_getHALErrno
(JNIEnv *, jclass)
{
return errno;
}
@@ -212,15 +471,12 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
* Method: getHALstrerror
* Signature: (I)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_edu_wpi_first_wpilibj_hal_HALUtil_getHALstrerror
(JNIEnv * env, jclass, jint errorCode)
JNIEXPORT jstring JNICALL Java_edu_wpi_first_wpilibj_hal_HALUtil_getHALstrerror
(JNIEnv * env, jclass, jint errorCode)
{
const char * msg = strerror(errno);
HALUTIL_LOG(logDEBUG) << "Calling HALUtil getHALstrerror errorCode=" << errorCode << " msg=" << msg;
return env->NewStringUTF(msg);
}
JNIEXPORT jint JNICALL
Java_edu_wpi_first_wpilibj_hal_HALUtil_pointerSize(JNIEnv*, jclass) {
return sizeof(void*);
}
} // extern "C"