From 940dc05ba3e2e6a0b2991dfe611efe06718263ec Mon Sep 17 00:00:00 2001 From: John Keiser Date: Sun, 21 Jun 1998 06:20:58 +0000 Subject: Initial Revision --- native/lib/DEPENDENCIES | 5 + native/lib/README | 27 +++ native/lib/STATUS | 8 + native/lib/jcl.c | 53 ++++++ native/lib/jcl.h | 23 +++ native/lib/jnilink.c | 162 ++++++++++++++++ native/lib/jnilink.h | 35 ++++ native/lib/primlib.c | 497 ++++++++++++++++++++++++++++++++++++++++++++++++ native/lib/primlib.h | 65 +++++++ 9 files changed, 875 insertions(+) create mode 100755 native/lib/DEPENDENCIES create mode 100755 native/lib/README create mode 100755 native/lib/STATUS create mode 100755 native/lib/jcl.c create mode 100755 native/lib/jcl.h create mode 100755 native/lib/jnilink.c create mode 100755 native/lib/jnilink.h create mode 100755 native/lib/primlib.c create mode 100644 native/lib/primlib.h (limited to 'native/lib') diff --git a/native/lib/DEPENDENCIES b/native/lib/DEPENDENCIES new file mode 100755 index 000000000..f70c669b7 --- /dev/null +++ b/native/lib/DEPENDENCIES @@ -0,0 +1,5 @@ +DEPENDENCIES for generic JCL libs: + +JCL: JNI +JNILINK: JNI,JCL,VMI +PRIMLIB: JNI,JCL diff --git a/native/lib/README b/native/lib/README new file mode 100755 index 000000000..1424b06b6 --- /dev/null +++ b/native/lib/README @@ -0,0 +1,27 @@ +README for generic JCL libs: + + +Jun 20 1998: John Keiser +Initial Revision: 1.1.0 + +OK, everything in the JCL libs is 1.1-compliant: if it uses +anything that could be VM-specific, it pawns the job off on +the VMI, whose job it is to interface to the virtual +machine. Some of these dependencies will go away with +JVMDI in 1.2, but until then, VMI is the way to go. + +jcl.h is for generically useful stuff: right now most of +the functions it has do some simple function, check for +errors, and throw an appropriate exception if an error +occurs. + +primlib.h is a way of caching the reflective types and the +wrapper types and does a little conversion between types to +boot. + +jnilink.h allows you to do typical linker functions: +caching of the methodID if it is final, private, or static +method and thus cannot be overriden; or re-resolution of +the methodID for each different class. Even re-resolution +can be made efficient by making it VM-specific; I.E. +caching the slot number instead of the name and signature. diff --git a/native/lib/STATUS b/native/lib/STATUS new file mode 100755 index 000000000..2f8ba2e31 --- /dev/null +++ b/native/lib/STATUS @@ -0,0 +1,8 @@ +STATUS for generic JCL libs: + +1.1: + +JNILINK: compiled, untested. +PRIMLIB: compiled, untested. +JCL: compiled, untested. + diff --git a/native/lib/jcl.c b/native/lib/jcl.c new file mode 100755 index 000000000..796715847 --- /dev/null +++ b/native/lib/jcl.c @@ -0,0 +1,53 @@ +#include +#include + +JNIEXPORT void JNICALL JCL_ThrowException(JNIEnv * env, char * className, char * errMsg) { + jclass excClass = (*env)->FindClass(env, className); + if((*env)->ExceptionOccurred(env)) { + return; + } + (*env)->ThrowNew(env, excClass, errMsg); +} + +JNIEXPORT void * JNICALL JCL_malloc(JNIEnv * env, size_t size) { + void * mem = malloc(size); + if(mem == NULL) { + JCL_ThrowException(env, "java/lang/OutOfMemoryError", "malloc() failed."); + return NULL; + } + return mem; +} + +JNIEXPORT char * JNICALL JCL_jstring_to_cstring(JNIEnv * env, jstring s) { + char* cstr; + if(s == NULL) { + JCL_ThrowException(env, "java/lang/NullPointerException","Null string"); + return NULL; + } + cstr = (char*)(*env)->GetStringUTFChars(env, s, NULL); + if(cstr == NULL) { + JCL_ThrowException(env, "java/lang/InternalError", "GetStringUTFChars() failed."); + return NULL; + } + return cstr; +} + +JNIEXPORT void JNICALL JCL_free_cstring(JNIEnv * env, jstring s, char * cstr) { + (*env)->ReleaseStringUTFChars(env, s, cstr); +} + +JNIEXPORT jint JNICALL JCL_MonitorEnter(JNIEnv * env, jobject o) { + jint retval = (*env)->MonitorEnter(env,o); + if(retval != 0) { + JCL_ThrowException(env, "java/lang/InternalError", "MonitorEnter() failed."); + } + return retval; +} + +JNIEXPORT jint JNICALL JCL_MonitorExit(JNIEnv * env, jobject o) { + jint retval = (*env)->MonitorExit(env,o); + if(retval != 0) { + JCL_ThrowException(env, "java/lang/InternalError", "MonitorExit() failed."); + } + return retval; +} diff --git a/native/lib/jcl.h b/native/lib/jcl.h new file mode 100755 index 000000000..657a181fc --- /dev/null +++ b/native/lib/jcl.h @@ -0,0 +1,23 @@ +#ifndef __JCL_H__ +#define __JCL_H__ + +#include + +JNIEXPORT void JNICALL JCL_ThrowException(JNIEnv * env, char * className, char * errMsg); +JNIEXPORT void * JNICALL JCL_malloc(JNIEnv * env, size_t size); +JNIEXPORT char * JNICALL JCL_jstring_to_cstring(JNIEnv * env, jstring s); +JNIEXPORT void JNICALL JCL_free_cstring(JNIEnv * env, jstring s, char * cstr); +JNIEXPORT jint JNICALL JCL_MonitorEnter(JNIEnv * env, jobject o); +JNIEXPORT jint JNICALL JCL_MonitorExit(JNIEnv * env, jobject o); + +#define JCL_RETHROW_EXCEPTION(env) if((*(env))->ExceptionOccurred((env)) != NULL) return NULL; + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#endif \ No newline at end of file diff --git a/native/lib/jnilink.c b/native/lib/jnilink.c new file mode 100755 index 000000000..31f8c1a19 --- /dev/null +++ b/native/lib/jnilink.c @@ -0,0 +1,162 @@ +#include "jnilink.h" +#include +#include +#include + +#include + +typedef struct jniMethodInfo { + int isStatic; + union { + struct { + char * name; + char * sig; + } dynamic; + jmethodID statID; + } data; +} jniMethodInfo; + +/* These functions are called to get the link pointers. */ +/* One possible optimization for Japhar would be to store the slot number of the method in the linkPtr. + * Another, which works for JNI too, is to see if the class or method is final and simply store the jmethodID. + * For JNI, the linkPtr must point to a struct containing the name and sig so that it can be re-resolved for + * every object. + */ +JNIEXPORT linkPtr JNICALL LINK_LinkMethod (JNIEnv * env, jclass clazz, char * name, char * sig) { + jniMethodInfo * m; + + jint classMods; + jint methodMods; + vmiError vmiErr; + + jmethodID theMethod; + + m = JCL_malloc(env, sizeof(jniMethodInfo)); + if(m == NULL) + return NULL; + + vmiErr = VMI_GetClassModifiers(env, clazz, &classMods); + if(vmiErr != VMI_ERROR_NONE) { + VMI_ThrowAppropriateException(env, vmiErr); + free(m); + return NULL; + } + + theMethod = (*env)->GetMethodID(env, clazz, name, sig); + if((*env)->ExceptionOccurred(env)) { + free(m); + return NULL; + } + + if(classMods & VMI_MOD_FINAL) { + m->isStatic = TRUE; + } else { + vmiErr = VMI_GetMethodModifiers(env, theMethod, &methodMods); + if(vmiErr != VMI_ERROR_NONE) { + VMI_ThrowAppropriateException(env, vmiErr); + free(m); + return NULL; + } + + if(methodMods & VMI_MOD_FINAL || methodMods & VMI_MOD_STATIC || methodMods & VMI_MOD_PRIVATE) { + m->isStatic = TRUE; + } else { + if(!strcmp(name,"")) + m->isStatic = TRUE; + else + m->isStatic = FALSE; + } + } + + if(m->isStatic) { + m->data.statID = theMethod; + } else { + m->data.dynamic.name = JCL_malloc(env, strlen(name) + 1); + if(m->data.dynamic.name == NULL) { + free(m); + return NULL; + } + + strcpy(m->data.dynamic.name, name); + + m->data.dynamic.sig = JCL_malloc(env, strlen(sig) + 1); + if(m->data.dynamic.sig == NULL) { + free(m->data.dynamic.name); + free(m->data.dynamic.sig); + return NULL; + } + + strcpy(m->data.dynamic.sig, sig); + } +} + +/* Do we need to re-resolve fields based on objects? I don't think so, but I could be wrong ... */ +JNIEXPORT linkPtr JNICALL LINK_LinkField (JNIEnv * env, jclass clazz, char * name, char * sig) { + return (linkPtr)(*env)->GetFieldID(env, clazz, name, sig); +} + +JNIEXPORT linkPtr JNICALL LINK_LinkClass (JNIEnv * env, char * name) { + jclass c = (*env)->FindClass(env, name); + if((*env)->ExceptionOccurred(env)) { + return NULL; + } + return (linkPtr)(*env)->NewGlobalRef(env, c); +} + + +/* The GetXXX functions can be inlined. */ +/* Note: GetMethod does actual resolution of the method based on the object type. + * The object in question *must* be of the correct type. No type checking is done. + * If the object is NULL, then the jmethodID will be NULL as well, and no exception + * will be thrown. If the method is not found, a MethodNotFoundException will be + * thrown. + */ +JNIEXPORT jmethodID JNICALL LINK_GetMethod (JNIEnv * env, linkPtr methodLink, jobject obj) { + jniMethodInfo * m; + jclass objClass; + + m = (jniMethodInfo *)methodLink; + if(m->isStatic) { + return m->data.statID; + } else { + if(obj == NULL) { + JCL_ThrowException(env, "java/lang/NullPointerException", "Attempt to access non-static method with null object in LINK_GetMethod"); + return NULL; + } + objClass = (*env)->GetObjectClass(env, obj); + return (*env)->GetMethodID(env, objClass, m->data.dynamic.name, m->data.dynamic.sig); + } +} + +JNIEXPORT jfieldID JNICALL LINK_GetField (JNIEnv * env, linkPtr fieldLink) { + return (jfieldID)fieldLink; +} + +JNIEXPORT jclass JNICALL LINK_GetClass (JNIEnv * env, linkPtr classLink) { + return (jclass)classLink; +} + + +/* These are for when the class referencing the symbols is unloaded; it +destroys any object references + * the linker might have kept around. + */ +JNIEXPORT void JNICALL LINK_UnlinkMethod (JNIEnv * env, linkPtr methodLink) { + jniMethodInfo * m = (jniMethodInfo *)methodLink; + if(m != NULL) { + if(!m->isStatic) { + if(m->data.dynamic.name != NULL) free(m->data.dynamic.name); + if(m->data.dynamic.sig != NULL) free(m->data.dynamic.sig); + } + free(m); + } +} + +JNIEXPORT void JNICALL LINK_UnlinkField (JNIEnv * env, linkPtr fieldLink) { + return; +} + +JNIEXPORT void JNICALL LINK_UnlinkClass (JNIEnv * env, linkPtr classLink) { + if(classLink != NULL) + (*env)->DeleteGlobalRef(env, (jclass)classLink); +} diff --git a/native/lib/jnilink.h b/native/lib/jnilink.h new file mode 100755 index 000000000..4d55da15e --- /dev/null +++ b/native/lib/jnilink.h @@ -0,0 +1,35 @@ +#ifndef __JNILINK_H__ +#define __JNILINK_H__ + +#include + +typedef void* linkPtr; + +/* These functions are called to get the link pointers. */ +/* One possible optimization for Japhar would be to store the slot number of the method in the linkPtr. + * Another, which works for JNI too, is to see if the class or method is final and simply store the jmethodID. + * For JNI, the linkPtr must point to a struct containing the name and sig so that it can be re-resolved for + * every object. + */ +JNIEXPORT linkPtr JNICALL LINK_LinkMethod (JNIEnv * env, jclass class, char * name, char * sig); +/* Do we need to re-resolve fields based on objects? I don't think so, but I could be wrong ... */ +JNIEXPORT linkPtr JNICALL LINK_LinkField (JNIEnv * env, jclass class, char * name, char * sig); +JNIEXPORT linkPtr JNICALL LINK_LinkClass (JNIEnv * env, char * name); + +/* The GetXXX functions can be inlined. */ +/* Note: GetMethod does actual resolution of the method based on the object type. + * The object in question *must* be of the correct type. No type checking is done. + */ +JNIEXPORT jmethodID JNICALL LINK_GetMethod (JNIEnv * env, linkPtr methodLink, jobject obj); +JNIEXPORT jfieldID JNICALL LINK_GetField (JNIEnv * env, linkPtr fieldLink); +JNIEXPORT jclass JNICALL LINK_GetClass (JNIEnv * env, linkPtr classLink); + +/* These are for when the class referencing the symbols is unloaded; it +destroys any object references + * the linker might have kept around. + */ +JNIEXPORT void JNICALL LINK_UnlinkMethod (JNIEnv * env, linkPtr methodLink); +JNIEXPORT void JNICALL LINK_UnlinkField (JNIEnv * env, linkPtr fieldLink); +JNIEXPORT void JNICALL LINK_UnlinkClass (JNIEnv * env, linkPtr classLink); + +#endif diff --git a/native/lib/primlib.c b/native/lib/primlib.c new file mode 100755 index 000000000..50feb9ae4 --- /dev/null +++ b/native/lib/primlib.c @@ -0,0 +1,497 @@ +#include +#include + +static jclass nativeWrapClass[PRIMLIB_NUMTYPES] = {NULL,NULL,NULL, NULL,NULL,NULL, + NULL,NULL,NULL, NULL,NULL,NULL}; + +static jclass nativeTypeClass[PRIMLIB_NUMTYPES] = {NULL,NULL,NULL, NULL,NULL,NULL, + NULL,NULL,NULL, NULL,NULL,NULL}; + +static jmethodID nativeWrapClassConstructor[PRIMLIB_NUMTYPES] = {NULL,NULL,NULL, NULL,NULL,NULL, + NULL,NULL,NULL, NULL,NULL,NULL}; + +static jmethodID nativeWrapClassAccessor[PRIMLIB_NUMTYPES] = {NULL,NULL,NULL, NULL,NULL,NULL, + NULL,NULL,NULL, NULL,NULL,NULL}; + +static char * nativeWrapClassName[PRIMLIB_NUMTYPES] = { + NULL, + NULL, + "java/lang/Boolean", + "java/lang/Byte", + "java/lang/Character", + "java/lang/Short", + "java/lang/Integer", + "java/lang/Long", + "java/lang/Float", + "java/lang/Double", + "java/lang/Void", + NULL + }; + +static char * nativeWrapClassConstructorSig[PRIMLIB_NUMTYPES] = { + NULL, + NULL, + "(Z)V", + "(B)V", + "(C)V", + "(S)V", + "(I)V", + "(J)V", + "(F)V", + "(D)V", + "()V", + NULL + }; + +static char * nativeWrapClassAccessorName[PRIMLIB_NUMTYPES] = { + NULL, + NULL, + "booleanValue", + "byteValue", + "charValue", + "shortValue", + "intValue", + "longValue", + "floatValue", + "doubleValue", + NULL, + NULL +}; + +static char * nativeWrapClassAccessorSig[PRIMLIB_NUMTYPES] = { + NULL, + NULL, + "()Z", + "()B", + "()C", + "()S", + "()I", + "()J", + "()F", + "()D", + NULL, + NULL +}; + + +JNIEXPORT jclass JNICALL PRIMLIB_GetNativeWrapClass(JNIEnv * env, int reflectType) { + jclass retval = nativeWrapClass[reflectType]; + if(retval == NULL) { + switch(reflectType) { + case PRIMLIB_BOOLEAN: + case PRIMLIB_BYTE: + case PRIMLIB_CHAR: + case PRIMLIB_SHORT: + case PRIMLIB_INT: + case PRIMLIB_LONG: + case PRIMLIB_FLOAT: + case PRIMLIB_DOUBLE: + case PRIMLIB_VOID: + return nativeWrapClass[reflectType] = (jclass)(*env)->NewGlobalRef(env, (*env)->FindClass(env, nativeWrapClassName[reflectType])); + case PRIMLIB_UNKNOWN: + case PRIMLIB_OBJECT: + case PRIMLIB_NULL: + default: + return NULL; + } + } else { + return retval; + } +} + +JNIEXPORT jclass JNICALL PRIMLIB_GetNativeTypeClass(JNIEnv * env, int reflectType) { + jclass retval = nativeTypeClass[reflectType]; + jfieldID typeField; + jclass wrapClass; + + if(retval == NULL) { + wrapClass = PRIMLIB_GetNativeWrapClass(env, reflectType); + if((*env)->ExceptionOccurred(env)) { + return NULL; + } + typeField = (*env)->GetFieldID(env, wrapClass, "TYPE", "Ljava/lang/Class"); + if((*env)->ExceptionOccurred(env)) { + return NULL; + } + switch(reflectType) { + case PRIMLIB_BOOLEAN: + case PRIMLIB_BYTE: + case PRIMLIB_CHAR: + case PRIMLIB_SHORT: + case PRIMLIB_INT: + case PRIMLIB_LONG: + case PRIMLIB_FLOAT: + case PRIMLIB_DOUBLE: + case PRIMLIB_VOID: + return nativeTypeClass[reflectType] = (jclass)(*env)->NewGlobalRef(env, (jclass)(*env)->GetStaticObjectField(env, wrapClass, typeField)); + case PRIMLIB_UNKNOWN: + case PRIMLIB_OBJECT: + case PRIMLIB_NULL: + default: + return NULL; + } + } else { + return retval; + } +} + +JNIEXPORT jmethodID JNICALL PRIMLIB_GetNativeWrapClassConstructor(JNIEnv * env, int reflectType) { + jmethodID retval = nativeWrapClassConstructor[reflectType]; + if(retval == NULL) { + switch(reflectType) { + case PRIMLIB_BOOLEAN: + case PRIMLIB_BYTE: + case PRIMLIB_CHAR: + case PRIMLIB_SHORT: + case PRIMLIB_INT: + case PRIMLIB_LONG: + case PRIMLIB_FLOAT: + case PRIMLIB_DOUBLE: + case PRIMLIB_VOID: + return nativeWrapClassConstructor[reflectType] = (*env)->GetMethodID(env, PRIMLIB_GetNativeWrapClass(env,reflectType), "", nativeWrapClassConstructorSig[reflectType]); + case PRIMLIB_UNKNOWN: + case PRIMLIB_OBJECT: + case PRIMLIB_NULL: + default: + return NULL; + } + } else { + return retval; + } +} + +JNIEXPORT jmethodID JNICALL PRIMLIB_GetNativeWrapClassAccessor(JNIEnv * env, int reflectType) { + jmethodID retval = nativeWrapClassAccessor[reflectType]; + if(retval == NULL) { + switch(reflectType) { + case PRIMLIB_BOOLEAN: + case PRIMLIB_BYTE: + case PRIMLIB_CHAR: + case PRIMLIB_SHORT: + case PRIMLIB_INT: + case PRIMLIB_LONG: + case PRIMLIB_FLOAT: + case PRIMLIB_DOUBLE: + return nativeWrapClassAccessor[reflectType] = (*env)->GetMethodID(env, PRIMLIB_GetNativeWrapClass(env,reflectType), nativeWrapClassAccessorName[reflectType], nativeWrapClassAccessorSig[reflectType]); + case PRIMLIB_VOID: + case PRIMLIB_UNKNOWN: + case PRIMLIB_OBJECT: + case PRIMLIB_NULL: + default: + return NULL; + } + } else { + return retval; + } +} + + + +JNIEXPORT jobject JNICALL PRIMLIB_WrapBoolean(JNIEnv * env, jboolean b) { + jmethodID construct = PRIMLIB_GetNativeWrapClassConstructor(env, PRIMLIB_BOOLEAN); + JCL_RETHROW_EXCEPTION(env); + return (*env)->NewObject(env, PRIMLIB_GetNativeWrapClass(env, PRIMLIB_BOOLEAN), construct, b); +} + +JNIEXPORT jobject JNICALL PRIMLIB_WrapByte (JNIEnv * env, jbyte b) { + jmethodID construct = PRIMLIB_GetNativeWrapClassConstructor(env, PRIMLIB_BYTE); + JCL_RETHROW_EXCEPTION(env); + return (*env)->NewObject(env, PRIMLIB_GetNativeWrapClass(env, PRIMLIB_BYTE), construct, b); +} + +JNIEXPORT jobject JNICALL PRIMLIB_WrapChar (JNIEnv * env, jchar c) { + jmethodID construct = PRIMLIB_GetNativeWrapClassConstructor(env, PRIMLIB_CHAR); + JCL_RETHROW_EXCEPTION(env); + return (*env)->NewObject(env, PRIMLIB_GetNativeWrapClass(env, PRIMLIB_CHAR), construct, c); +} + +JNIEXPORT jobject JNICALL PRIMLIB_WrapShort (JNIEnv * env, jshort s) { + jmethodID construct = PRIMLIB_GetNativeWrapClassConstructor(env, PRIMLIB_SHORT); + JCL_RETHROW_EXCEPTION(env); + return (*env)->NewObject(env, PRIMLIB_GetNativeWrapClass(env, PRIMLIB_SHORT), construct, s); +} + +JNIEXPORT jobject JNICALL PRIMLIB_WrapInt (JNIEnv * env, jint i) { + jmethodID construct = PRIMLIB_GetNativeWrapClassConstructor(env, PRIMLIB_INT); + JCL_RETHROW_EXCEPTION(env); + return (*env)->NewObject(env, PRIMLIB_GetNativeWrapClass(env, PRIMLIB_INT), construct, i); +} + +JNIEXPORT jobject JNICALL PRIMLIB_WrapLong (JNIEnv * env, jlong l) { + jmethodID construct = PRIMLIB_GetNativeWrapClassConstructor(env, PRIMLIB_LONG); + JCL_RETHROW_EXCEPTION(env); + return (*env)->NewObject(env, PRIMLIB_GetNativeWrapClass(env, PRIMLIB_LONG), construct, l); +} + +JNIEXPORT jobject JNICALL PRIMLIB_WrapFloat (JNIEnv * env, jfloat f) { + jmethodID construct = PRIMLIB_GetNativeWrapClassConstructor(env, PRIMLIB_FLOAT); + JCL_RETHROW_EXCEPTION(env); + return (*env)->NewObject(env, PRIMLIB_GetNativeWrapClass(env, PRIMLIB_FLOAT), construct, f); +} + +JNIEXPORT jobject JNICALL PRIMLIB_WrapDouble (JNIEnv * env, jdouble d) { + jmethodID construct = PRIMLIB_GetNativeWrapClassConstructor(env, PRIMLIB_DOUBLE); + JCL_RETHROW_EXCEPTION(env); + return (*env)->NewObject(env, PRIMLIB_GetNativeWrapClass(env, PRIMLIB_DOUBLE), construct, d); +} + + +JNIEXPORT jboolean JNICALL PRIMLIB_UnwrapBoolean(JNIEnv * env, jobject obj) { + if((*env)->IsInstanceOf(env, obj, PRIMLIB_GetNativeWrapClass(env, PRIMLIB_BOOLEAN))) { + return PRIMLIB_GetBooleanObjectValue(env, obj); + } else { + JCL_ThrowException(env, "java/lang/IllegalArgumentException", "Argument not of correct type."); + } +} + +JNIEXPORT jbyte JNICALL PRIMLIB_UnwrapByte(JNIEnv * env, jobject obj) { + if((*env)->IsInstanceOf(env, obj, PRIMLIB_GetNativeWrapClass(env, PRIMLIB_BYTE))) { + return PRIMLIB_GetByteObjectValue(env, obj); + } else { + JCL_ThrowException(env, "java/lang/IllegalArgumentException", "Argument not of correct type."); + } +} + +JNIEXPORT jshort JNICALL PRIMLIB_UnwrapShort(JNIEnv * env, jobject obj) { + if((*env)->IsInstanceOf(env, obj, PRIMLIB_GetNativeWrapClass(env, PRIMLIB_SHORT))) { + return PRIMLIB_GetShortObjectValue(env, obj); + } else if((*env)->IsInstanceOf(env, obj, PRIMLIB_GetNativeWrapClass(env, PRIMLIB_BYTE))) { + return (jshort)PRIMLIB_GetByteObjectValue(env, obj); + } else { + JCL_ThrowException(env, "java/lang/IllegalArgumentException", "Argument not of correct type."); + } +} + +JNIEXPORT jchar JNICALL PRIMLIB_UnwrapChar(JNIEnv * env, jobject obj) { + if((*env)->IsInstanceOf(env, obj, PRIMLIB_GetNativeWrapClass(env, PRIMLIB_CHAR))) { + return PRIMLIB_GetCharObjectValue(env, obj); + } else { + JCL_ThrowException(env, "java/lang/IllegalArgumentException", "Argument not of correct type."); + } +} + +JNIEXPORT jint JNICALL PRIMLIB_UnwrapInt(JNIEnv * env, jobject obj) { + if((*env)->IsInstanceOf(env, obj, PRIMLIB_GetNativeWrapClass(env, PRIMLIB_INT))) { + return PRIMLIB_GetIntObjectValue(env, obj); + } else if((*env)->IsInstanceOf(env, obj, PRIMLIB_GetNativeWrapClass(env, PRIMLIB_SHORT))) { + return (jint)PRIMLIB_GetShortObjectValue(env, obj); + } else if((*env)->IsInstanceOf(env, obj, PRIMLIB_GetNativeWrapClass(env, PRIMLIB_CHAR))) { + return (jint)PRIMLIB_GetCharObjectValue(env, obj); + } else if((*env)->IsInstanceOf(env, obj, PRIMLIB_GetNativeWrapClass(env, PRIMLIB_BYTE))) { + return (jint)PRIMLIB_GetByteObjectValue(env, obj); + } else { + JCL_ThrowException(env, "java/lang/IllegalArgumentException", "Argument not of correct type."); + } +} + +JNIEXPORT jlong JNICALL PRIMLIB_UnwrapLong(JNIEnv * env, jobject obj) { + if((*env)->IsInstanceOf(env, obj, PRIMLIB_GetNativeWrapClass(env, PRIMLIB_LONG))) { + return PRIMLIB_GetLongObjectValue(env, obj); + } else if((*env)->IsInstanceOf(env, obj, PRIMLIB_GetNativeWrapClass(env, PRIMLIB_INT))) { + return (jlong)PRIMLIB_GetIntObjectValue(env, obj); + } else if((*env)->IsInstanceOf(env, obj, PRIMLIB_GetNativeWrapClass(env, PRIMLIB_SHORT))) { + return (jlong)PRIMLIB_GetShortObjectValue(env, obj); + } else if((*env)->IsInstanceOf(env, obj, PRIMLIB_GetNativeWrapClass(env, PRIMLIB_CHAR))) { + return (jlong)PRIMLIB_GetCharObjectValue(env, obj); + } else if((*env)->IsInstanceOf(env, obj, PRIMLIB_GetNativeWrapClass(env, PRIMLIB_BYTE))) { + return (jlong)PRIMLIB_GetByteObjectValue(env, obj); + } else { + JCL_ThrowException(env, "java/lang/IllegalArgumentException", "Argument not of correct type."); + } +} + +JNIEXPORT jfloat JNICALL PRIMLIB_UnwrapFloat(JNIEnv * env, jobject obj) { + if((*env)->IsInstanceOf(env, obj, PRIMLIB_GetNativeWrapClass(env, PRIMLIB_FLOAT))) { + return PRIMLIB_GetFloatObjectValue(env, obj); + } else if((*env)->IsInstanceOf(env, obj, PRIMLIB_GetNativeWrapClass(env, PRIMLIB_LONG))) { + return (jfloat)PRIMLIB_GetLongObjectValue(env, obj); + } else if((*env)->IsInstanceOf(env, obj, PRIMLIB_GetNativeWrapClass(env, PRIMLIB_INT))) { + return (jfloat)PRIMLIB_GetIntObjectValue(env, obj); + } else if((*env)->IsInstanceOf(env, obj, PRIMLIB_GetNativeWrapClass(env, PRIMLIB_SHORT))) { + return (jfloat)PRIMLIB_GetShortObjectValue(env, obj); + } else if((*env)->IsInstanceOf(env, obj, PRIMLIB_GetNativeWrapClass(env, PRIMLIB_CHAR))) { + return (jfloat)PRIMLIB_GetCharObjectValue(env, obj); + } else if((*env)->IsInstanceOf(env, obj, PRIMLIB_GetNativeWrapClass(env, PRIMLIB_BYTE))) { + return (jfloat)PRIMLIB_GetByteObjectValue(env, obj); + } else { + JCL_ThrowException(env, "java/lang/IllegalArgumentException", "Argument not of correct type."); + } +} + +JNIEXPORT jdouble JNICALL PRIMLIB_UnwrapDouble(JNIEnv * env, jobject obj) { + if((*env)->IsInstanceOf(env, obj, PRIMLIB_GetNativeWrapClass(env, PRIMLIB_DOUBLE))) { + return PRIMLIB_GetDoubleObjectValue(env, obj); + } else if((*env)->IsInstanceOf(env, obj, PRIMLIB_GetNativeWrapClass(env, PRIMLIB_FLOAT))) { + return (jdouble)PRIMLIB_GetFloatObjectValue(env, obj); + } else if((*env)->IsInstanceOf(env, obj, PRIMLIB_GetNativeWrapClass(env, PRIMLIB_LONG))) { + return (jdouble)PRIMLIB_GetLongObjectValue(env, obj); + } else if((*env)->IsInstanceOf(env, obj, PRIMLIB_GetNativeWrapClass(env, PRIMLIB_INT))) { + return (jdouble)PRIMLIB_GetIntObjectValue(env, obj); + } else if((*env)->IsInstanceOf(env, obj, PRIMLIB_GetNativeWrapClass(env, PRIMLIB_SHORT))) { + return (jdouble)PRIMLIB_GetShortObjectValue(env, obj); + } else if((*env)->IsInstanceOf(env, obj, PRIMLIB_GetNativeWrapClass(env, PRIMLIB_CHAR))) { + return (jdouble)PRIMLIB_GetCharObjectValue(env, obj); + } else if((*env)->IsInstanceOf(env, obj, PRIMLIB_GetNativeWrapClass(env, PRIMLIB_BYTE))) { + return (jdouble)PRIMLIB_GetByteObjectValue(env, obj); + } else { + JCL_ThrowException(env, "java/lang/IllegalArgumentException", "Argument not of correct type."); + } +} + +JNIEXPORT jint JNICALL PRIMLIB_GetReflectiveWrapperType(JNIEnv * env, jobject obj) { + jclass typeClass; + if(obj == NULL) { + return PRIMLIB_NULL; + } + + typeClass = PRIMLIB_GetNativeWrapClass(env, PRIMLIB_DOUBLE); + if((*env)->IsInstanceOf(env, obj, typeClass)) { + return PRIMLIB_DOUBLE; + } + typeClass = PRIMLIB_GetNativeWrapClass(env, PRIMLIB_FLOAT); + if((*env)->IsInstanceOf(env, obj, typeClass)) { + return PRIMLIB_FLOAT; + } + typeClass = PRIMLIB_GetNativeWrapClass(env, PRIMLIB_LONG); + if((*env)->IsInstanceOf(env, obj, typeClass)) { + return PRIMLIB_LONG; + } + typeClass = PRIMLIB_GetNativeWrapClass(env, PRIMLIB_INT); + if((*env)->IsInstanceOf(env, obj, typeClass)) { + return PRIMLIB_INT; + } + typeClass = PRIMLIB_GetNativeWrapClass(env, PRIMLIB_CHAR); + if((*env)->IsInstanceOf(env, obj, typeClass)) { + return PRIMLIB_CHAR; + } + typeClass = PRIMLIB_GetNativeWrapClass(env, PRIMLIB_SHORT); + if((*env)->IsInstanceOf(env, obj, typeClass)) { + return PRIMLIB_SHORT; + } + typeClass = PRIMLIB_GetNativeWrapClass(env, PRIMLIB_BYTE); + if((*env)->IsInstanceOf(env, obj, typeClass)) { + return PRIMLIB_BYTE; + } + typeClass = PRIMLIB_GetNativeWrapClass(env, PRIMLIB_BOOLEAN); + if((*env)->IsInstanceOf(env, obj, typeClass)) { + return PRIMLIB_BOOLEAN; + } + typeClass = PRIMLIB_GetNativeWrapClass(env, PRIMLIB_VOID); + if((*env)->IsInstanceOf(env, obj, typeClass)) { + return PRIMLIB_VOID; + } + return PRIMLIB_OBJECT; +} + +JNIEXPORT jint JNICALL PRIMLIB_GetReflectiveType(JNIEnv * env, jclass returnType) { + jclass typeClass = PRIMLIB_GetNativeTypeClass(env, PRIMLIB_DOUBLE); + if((*env)->IsAssignableFrom(env, returnType, typeClass)) { + return PRIMLIB_DOUBLE; + } + typeClass = PRIMLIB_GetNativeTypeClass(env, PRIMLIB_FLOAT); + if((*env)->IsAssignableFrom(env, returnType, typeClass)) { + return PRIMLIB_FLOAT; + } + typeClass = PRIMLIB_GetNativeTypeClass(env, PRIMLIB_LONG); + if((*env)->IsAssignableFrom(env, returnType, typeClass)) { + return PRIMLIB_LONG; + } + typeClass = PRIMLIB_GetNativeTypeClass(env, PRIMLIB_INT); + if((*env)->IsAssignableFrom(env, returnType, typeClass)) { + return PRIMLIB_INT; + } + typeClass = PRIMLIB_GetNativeTypeClass(env, PRIMLIB_CHAR); + if((*env)->IsAssignableFrom(env, returnType, typeClass)) { + return PRIMLIB_CHAR; + } + typeClass = PRIMLIB_GetNativeTypeClass(env, PRIMLIB_SHORT); + if((*env)->IsAssignableFrom(env, returnType, typeClass)) { + return PRIMLIB_SHORT; + } + typeClass = PRIMLIB_GetNativeTypeClass(env, PRIMLIB_BYTE); + if((*env)->IsAssignableFrom(env, returnType, typeClass)) { + return PRIMLIB_BYTE; + } + typeClass = PRIMLIB_GetNativeTypeClass(env, PRIMLIB_BOOLEAN); + if((*env)->IsAssignableFrom(env, returnType, typeClass)) { + return PRIMLIB_BOOLEAN; + } + typeClass = PRIMLIB_GetNativeTypeClass(env, PRIMLIB_VOID); + if((*env)->IsAssignableFrom(env, returnType, typeClass)) { + return PRIMLIB_VOID; + } + return PRIMLIB_OBJECT; +} + + +JNIEXPORT jboolean JNICALL PRIMLIB_GetBooleanObjectValue(JNIEnv * env, jobject obj) { + jmethodID acc = PRIMLIB_GetNativeWrapClassAccessor(env, PRIMLIB_BOOLEAN); + return (*env)->CallBooleanMethod(env, obj, acc); +} + +JNIEXPORT jbyte JNICALL PRIMLIB_GetByteObjectValue(JNIEnv * env, jobject obj) { + jmethodID acc = PRIMLIB_GetNativeWrapClassAccessor(env, PRIMLIB_BYTE); + return (*env)->CallByteMethod(env, obj, acc); +} + +JNIEXPORT jshort JNICALL PRIMLIB_GetShortObjectValue(JNIEnv * env, jobject obj) { + jmethodID acc = PRIMLIB_GetNativeWrapClassAccessor(env, PRIMLIB_SHORT); + return (*env)->CallShortMethod(env, obj, acc); +} + +JNIEXPORT jchar JNICALL PRIMLIB_GetCharObjectValue(JNIEnv * env, jobject obj) { + jmethodID acc = PRIMLIB_GetNativeWrapClassAccessor(env, PRIMLIB_CHAR); + return (*env)->CallCharMethod(env, obj, acc); +} + +JNIEXPORT jint JNICALL PRIMLIB_GetIntObjectValue(JNIEnv * env, jobject obj) { + jmethodID acc = PRIMLIB_GetNativeWrapClassAccessor(env, PRIMLIB_INT); + return (*env)->CallIntMethod(env, obj, acc); +} + +JNIEXPORT jlong JNICALL PRIMLIB_GetLongObjectValue(JNIEnv * env, jobject obj) { + jmethodID acc = PRIMLIB_GetNativeWrapClassAccessor(env, PRIMLIB_LONG); + return (*env)->CallLongMethod(env, obj, acc); +} + +JNIEXPORT jfloat JNICALL PRIMLIB_GetFloatObjectValue(JNIEnv * env, jobject obj) { + jmethodID acc = PRIMLIB_GetNativeWrapClassAccessor(env, PRIMLIB_FLOAT); + return (*env)->CallFloatMethod(env, obj, acc); +} + +JNIEXPORT jdouble JNICALL PRIMLIB_GetDoubleObjectValue(JNIEnv * env, jobject obj) { + jmethodID acc = PRIMLIB_GetNativeWrapClassAccessor(env, PRIMLIB_DOUBLE); + return (*env)->CallDoubleMethod(env, obj, acc); +} + + + +JNIEXPORT jvalue JNICALL PRIMLIB_UnwrapJValue(JNIEnv* env, jobject obj, jclass classType) { + jvalue retval; + jint objType = PRIMLIB_GetReflectiveType(env, classType); + if(objType == PRIMLIB_BOOLEAN) { + retval.z = PRIMLIB_UnwrapBoolean(env,obj); + } else if(objType == PRIMLIB_BYTE) { + retval.b = PRIMLIB_UnwrapByte(env,obj); + } else if(objType == PRIMLIB_CHAR) { + retval.c = PRIMLIB_UnwrapChar(env,obj); + } else if(objType == PRIMLIB_SHORT) { + retval.s = PRIMLIB_UnwrapShort(env,obj); + } else if(objType == PRIMLIB_INT) { + retval.i = PRIMLIB_UnwrapInt(env,obj); + } else if(objType == PRIMLIB_LONG) { + retval.j = PRIMLIB_UnwrapLong(env,obj); + } else if(objType == PRIMLIB_FLOAT) { + retval.f = PRIMLIB_UnwrapFloat(env,obj); + } else if(objType == PRIMLIB_DOUBLE) { + retval.d = PRIMLIB_UnwrapDouble(env,obj); + } else { + if(obj != NULL && !(*env)->IsInstanceOf(env, obj, classType)) { + JCL_ThrowException(env, "java/lang/IllegalArgumentException", "Argument not of correct object type."); + return retval; + } + retval.l = obj; + } + return retval; +} + diff --git a/native/lib/primlib.h b/native/lib/primlib.h new file mode 100644 index 000000000..1c1e3dbe4 --- /dev/null +++ b/native/lib/primlib.h @@ -0,0 +1,65 @@ +#ifndef __PRIMLIB_H__ +#define __PRIMLIB_H__ + +#include + +#define PRIMLIB_UNKNOWN 0 +#define PRIMLIB_OBJECT 1 +#define PRIMLIB_BOOLEAN 2 +#define PRIMLIB_BYTE 3 +#define PRIMLIB_CHAR 4 +#define PRIMLIB_SHORT 5 +#define PRIMLIB_INT 6 +#define PRIMLIB_LONG 7 +#define PRIMLIB_FLOAT 8 +#define PRIMLIB_DOUBLE 9 +#define PRIMLIB_VOID 10 +#define PRIMLIB_NULL 11 +#define PRIMLIB_NUMTYPES 12 + +/* Low-level primitive class accessor functions. */ +JNIEXPORT jclass JNICALL PRIMLIB_GetNativeWrapClass(JNIEnv * env, int reflectType); +JNIEXPORT jclass JNICALL PRIMLIB_GetNativeTypeClass(JNIEnv * env, int reflectType); +JNIEXPORT jmethodID JNICALL PRIMLIB_GetNativeWrapClassConstructor(JNIEnv * env, int reflectType); +JNIEXPORT jmethodID JNICALL PRIMLIB_GetNativeWrapClassAccessor(JNIEnv * env, int reflectType); + +/* Type discovery functions: WrapperType finds out j.l.Boolean/Byte/etc., and + Type finds out j.l.Boolean.TYPE, etc. +*/ +JNIEXPORT jint JNICALL PRIMLIB_GetReflectiveWrapperType(JNIEnv * env, jobject obj); +JNIEXPORT jint JNICALL PRIMLIB_GetReflectiveType(JNIEnv * env, jclass returnType); + +/* Constructor functions. */ +JNIEXPORT jobject JNICALL PRIMLIB_WrapBoolean(JNIEnv * env, jboolean b); +JNIEXPORT jobject JNICALL PRIMLIB_WrapByte (JNIEnv * env, jbyte b); +JNIEXPORT jobject JNICALL PRIMLIB_WrapChar (JNIEnv * env, jchar c); +JNIEXPORT jobject JNICALL PRIMLIB_WrapShort (JNIEnv * env, jshort s); +JNIEXPORT jobject JNICALL PRIMLIB_WrapInt (JNIEnv * env, jint i); +JNIEXPORT jobject JNICALL PRIMLIB_WrapLong (JNIEnv * env, jlong l); +JNIEXPORT jobject JNICALL PRIMLIB_WrapFloat (JNIEnv * env, jfloat f); +JNIEXPORT jobject JNICALL PRIMLIB_WrapDouble (JNIEnv * env, jdouble d); + +/* Widening conversion unwrapping functions. */ +JNIEXPORT jboolean JNICALL PRIMLIB_UnwrapBoolean(JNIEnv * env, jobject obj); +JNIEXPORT jbyte JNICALL PRIMLIB_UnwrapByte (JNIEnv * env, jobject obj); +JNIEXPORT jshort JNICALL PRIMLIB_UnwrapShort (JNIEnv * env, jobject obj); +JNIEXPORT jchar JNICALL PRIMLIB_UnwrapChar (JNIEnv * env, jobject obj); +JNIEXPORT jint JNICALL PRIMLIB_UnwrapInt (JNIEnv * env, jobject obj); +JNIEXPORT jlong JNICALL PRIMLIB_UnwrapLong (JNIEnv * env, jobject obj); +JNIEXPORT jfloat JNICALL PRIMLIB_UnwrapFloat (JNIEnv * env, jobject obj); +JNIEXPORT jdouble JNICALL PRIMLIB_UnwrapDouble (JNIEnv * env, jobject obj); + +/* Simple unwrapping functions. Objects *must* be of correct type. */ +JNIEXPORT jboolean JNICALL PRIMLIB_GetBooleanObjectValue(JNIEnv * env, jobject obj); +JNIEXPORT jbyte JNICALL PRIMLIB_GetByteObjectValue (JNIEnv * env, jobject obj); +JNIEXPORT jshort JNICALL PRIMLIB_GetShortObjectValue (JNIEnv * env, jobject obj); +JNIEXPORT jchar JNICALL PRIMLIB_GetCharObjectValue (JNIEnv * env, jobject obj); +JNIEXPORT jint JNICALL PRIMLIB_GetIntObjectValue (JNIEnv * env, jobject obj); +JNIEXPORT jlong JNICALL PRIMLIB_GetLongObjectValue (JNIEnv * env, jobject obj); +JNIEXPORT jfloat JNICALL PRIMLIB_GetFloatObjectValue (JNIEnv * env, jobject obj); +JNIEXPORT jdouble JNICALL PRIMLIB_GetDoubleObjectValue (JNIEnv * env, jobject obj); + +/* jvalue conversion: Unwrap obj to the type of classType, with widening conversion. */ +JNIEXPORT jvalue JNICALL PRIMLIB_UnwrapJValue(JNIEnv* env, jobject obj, jclass classType); + +#endif -- cgit v1.2.1