diff options
author | Sven Gothel <[email protected]> | 2000-11-18 06:43:49 +0000 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2000-11-18 06:43:49 +0000 |
commit | 880653d31a8f1ff8384fdbc75b84934bceecfdb8 (patch) | |
tree | bdafb71416f176d2a4b73bf716c9dc3f13685a8b /CNativeCode/jni12tools.c |
Initial revision
Diffstat (limited to 'CNativeCode/jni12tools.c')
-rw-r--r-- | CNativeCode/jni12tools.c | 516 |
1 files changed, 516 insertions, 0 deletions
diff --git a/CNativeCode/jni12tools.c b/CNativeCode/jni12tools.c new file mode 100644 index 0000000..8e2cc37 --- /dev/null +++ b/CNativeCode/jni12tools.c @@ -0,0 +1,516 @@ +#include <string.h> +#include "jnitools.h" + +#ifdef __BUILTIN_VA_ARG_INCR + /* Special stuff for the SunOS port ... */ + va_list __builtin_va_arg_incr = 0; + va_list __builtin_va_alist = 0; +#endif + +static int isinit = 0; +static jclass classString=0; +static jmethodID String_getBytes_ID=0; +static jmethodID String_init_ID=0; + +static int init(JNIEnv *env) +{ + classString = (*env)->FindClass(env, "java/lang/String"); + if(classString) + { + String_getBytes_ID = + (*env)->GetMethodID(env, classString, "getBytes", "()[B"); + if(!String_getBytes_ID) return 0; + String_init_ID = (*env)->GetMethodID(env, classString, "<init>", "([B)V"); + if(!String_init_ID) return 0; + } else return 0; + return 1; +} + +/* Throw an exception by name */ +void LIBAPIENTRY jnitoolsThrowByName(JNIEnv *env, const char *name, const char *msg, ...) +{ + static char buffer[1024]; + va_list va; + jclass cls = 0; + + if(!isinit && init(env)) isinit=1; + + va_start(va, msg); + + #ifdef NO_VSNPRINTF + (void) vsprintf(buffer, msg, va); /* dangerous -> stack overwrite ... */ + #else + (void) vsnprintf(buffer, 1023, msg, va); + #endif + buffer[1023]=0; + + va_end(va); + + cls = (*env)->FindClass(env, name); + + if (cls != 0) /* Otherwise an exception has already been thrown */ + (*env)->ThrowNew(env, cls, buffer); + + /* It's a good practice to clean up the local references. */ + (*env)->DeleteLocalRef(env, cls); +} + +/* Translates a Java string to a C string using the String.getBytes + * method, which uses default local encoding. + */ +char * LIBAPIENTRY jnitoolsGetJavaString(JNIEnv *env, jstring jstr) +{ + jbyteArray hab = 0; + jthrowable exc; + char *result = 0; + + if(!isinit && init(env)) isinit=1; + + hab = (*env)->CallObjectMethod(env, jstr, String_getBytes_ID); + exc = (*env)->ExceptionOccurred(env); + if (!exc) { + jint len = (*env)->GetArrayLength(env, hab); + result = (char *)malloc(len + 1); + if (result == 0) { + jnitoolsThrowByName(env, "java/lang/OutOfMemoryError", 0); + (*env)->DeleteLocalRef(env, hab); + return 0; + } + (*env)->GetByteArrayRegion(env, hab, 0, len, (jbyte *)result); + result[len] = 0; /* NULL-terminate */ + } else { + (*env)->DeleteLocalRef(env, exc); + } + (*env)->DeleteLocalRef(env, hab); + return result; +} + +/** + * signature: e.g. "(II[I)V" for "void <name>(int, int, int[])" + * + * argIndex: 0-n argument index of the method signature + * -1 return type + */ +static JavaBasicType _jnitoolsGetJavaBasicTypeAndArgLen(JNIEnv *env, + const char * signature, int argIndex, + const char * errText, + int * argLen) +{ + int i, j, arg, argend, arraydim; + char c, *help; + JavaBasicType jbt = T_NOPE; + + if(!isinit && init(env)) isinit=1; + + *argLen=0; + + if(signature==NULL) return T_NOPE; + j=strlen(signature); + + for(i=0, arg=0, argend=0, arraydim=0; i<j; i++) + { + c=signature[i]; + if(c=='(') continue; + if(c==')') { argend=1; continue; } + if(c=='[') { arraydim++; continue; } + switch (c) + { + case 'L': + help = strchr(signature+i, ';'); + if(help==NULL) + { + jnitoolsThrowByName(env, + "java/lang/IllegalArgumentException", + "%s(arg #%d): invalid signature (inv. object) at %d <%s>\n", + errText, argIndex+1, i, signature); + return T_NOPE; + } + jbt = (arraydim==0)?T_OBJECT:T_OBJECT_ARRAY; + i = help-signature; + arraydim=0; + break; + case 'V': + if(arraydim>0) + { + jnitoolsThrowByName(env, + "java/lang/IllegalArgumentException", + "%s(arg #%d): invalid signature (void array) at %d <%s>\n", + errText, argIndex+1, i, signature); + return T_NOPE; + } + jbt = T_VOID; + arraydim=0; + break; + case 'Z': + jbt = (arraydim==0)?T_BOOLEAN:T_BOOLEAN_ARRAY; + arraydim=0; + break; + case 'B': + jbt = (arraydim==0)?T_BYTE:T_BYTE_ARRAY; + arraydim=0; + break; + case 'C': + jbt = (arraydim==0)?T_CHAR:T_CHAR_ARRAY; + arraydim=0; + break; + case 'S': + jbt = (arraydim==0)?T_SHORT:T_SHORT_ARRAY; + arraydim=0; + break; + case 'I': + jbt = (arraydim==0)?T_INT:T_INT_ARRAY; + arraydim=0; + break; + case 'J': + jbt = (arraydim==0)?T_LONG:T_LONG_ARRAY; + arraydim=0; + break; + case 'F': + jbt = (arraydim==0)?T_FLOAT:T_FLOAT_ARRAY; + arraydim=0; + break; + case 'D': + jbt = (arraydim==0)?T_DOUBLE:T_DOUBLE_ARRAY; + arraydim=0; + break; + } + if( (argIndex >=0 && arg==argIndex) || + (argIndex==-1 && argend==1) + ) + { + *argLen=arg; + return jbt; + } + arg++; + } + return T_NOPE; +} + +/** + * signature: e.g. "(II[I)V" for "void <name>(int, int, int[])" + * + * argIndex: 0-n argument index of the method signature + * -1 return type + */ +int LIBAPIENTRY jnitoolsGetArgNumber(JNIEnv *env, + const char * signature, + const char * errText) +{ + int num = 0; + (void) _jnitoolsGetJavaBasicTypeAndArgLen(env, + signature, -1, + errText, + &num); + return num; +} + +/** + * signature: e.g. "(II[I)V" for "void <name>(int, int, int[])" + * + * argIndex: 0-n argument index of the method signature + * -1 return type + */ +JavaBasicType LIBAPIENTRY jnitoolsGetJavaBasicType(JNIEnv *env, + const char * signature, int argIndex, + const char * errText) +{ + int num = 0; + JavaBasicType jbt = _jnitoolsGetJavaBasicTypeAndArgLen(env, + signature, argIndex, + errText, + &num); + return jbt; +} + +jarray LIBAPIENTRY jnitoolsNativeArray2JavaArray (JNIEnv *env, JavaBasicType jbt, + void *data, int dataArrayLen, + const char * errText, int arg) +{ + jarray res = 0; + + if(!isinit && init(env)) isinit=1; + + switch(jbt) + { + case T_BOOLEAN_ARRAY: + res = (*env)->NewBooleanArray(env, dataArrayLen); + if(data!=NULL) + (*env)->SetBooleanArrayRegion(env, (jbooleanArray)res, + 0, dataArrayLen, + (jboolean*)data); + break; + case T_BYTE_ARRAY: + res = (*env)->NewByteArray(env, dataArrayLen); + if(data!=NULL) + (*env)->SetByteArrayRegion(env, (jbyteArray)res, + 0, dataArrayLen, (jbyte*)data); + break; + case T_CHAR_ARRAY: + res = (*env)->NewCharArray(env, dataArrayLen); + if(data!=NULL) + (*env)->SetCharArrayRegion(env, (jcharArray)res, + 0, dataArrayLen, (jchar*)data); + break; + case T_SHORT_ARRAY: + res = (*env)->NewShortArray(env, dataArrayLen); + if(data!=NULL) + (*env)->SetShortArrayRegion(env, (jshortArray)res, + 0, dataArrayLen, (jshort*)data); + break; + case T_INT_ARRAY: + res = (*env)->NewIntArray(env, dataArrayLen); + if(data!=NULL) + (*env)->SetIntArrayRegion(env, (jintArray)res, + 0, dataArrayLen, (jint*)data); + break; + case T_LONG_ARRAY: + res = (*env)->NewLongArray(env, dataArrayLen); + if(data!=NULL) + (*env)->SetLongArrayRegion(env, (jlongArray)res, + 0, dataArrayLen, (jlong*)data); + break; + case T_FLOAT_ARRAY: + res = (*env)->NewFloatArray(env, dataArrayLen); + if(data!=NULL) + (*env)->SetFloatArrayRegion(env, (jfloatArray)res, + 0, dataArrayLen, (jfloat*)data); + break; + case T_DOUBLE_ARRAY: + res = (*env)->NewDoubleArray(env, dataArrayLen); + if(data!=NULL) + (*env)->SetDoubleArrayRegion(env, (jdoubleArray)res, + 0, dataArrayLen, (jdouble*)data); + break; + default: + jnitoolsThrowByName(env, "java/lang/IllegalArgumentException", + "%s(arg #%d): Type is not an array", + errText, arg); + return 0; + } + return res; +} + +jarray LIBAPIENTRY jnitoolsNativePtrArray2JavaArray (JNIEnv *env, + JavaBasicType jbt, + void *data[/*pointerNumber*/], + int pointerNumber, + int dataArrayLen, + const char * errText, int arg) + +{ + unsigned char * buffer = NULL; + jarray res = 0; + int i; + int setLenElems = dataArrayLen/pointerNumber; + int setLenBytes = 0; + + + if(!isinit && init(env)) isinit=1; + + switch(jbt) + { + case T_BYTE_ARRAY: + setLenBytes = setLenElems * sizeof(jbyte) ; + break; + case T_CHAR_ARRAY: + setLenBytes = setLenElems * sizeof(jchar) ; + break; + case T_SHORT_ARRAY: + setLenBytes = setLenElems * sizeof(jshort) ; + break; + case T_BOOLEAN_ARRAY: + setLenBytes = setLenElems * sizeof(jboolean) ; + break; + case T_INT_ARRAY: + setLenBytes = setLenElems * sizeof(jint) ; + break; + case T_LONG_ARRAY: + setLenBytes = setLenElems * sizeof(jlong) ; + break; + case T_FLOAT_ARRAY: + setLenBytes = setLenElems * sizeof(jfloat) ; + break; + case T_DOUBLE_ARRAY: + setLenBytes = setLenElems * sizeof(jdouble) ; + break; + default: + jnitoolsThrowByName(env, "java/lang/IllegalArgumentException", + "%s(arg #%d): Type is not an array", + errText, arg); + return 0; + } + buffer = calloc (pointerNumber, setLenBytes); + if(buffer==NULL) + { + jnitoolsThrowByName(env, "java/lang/Exception", + "%s(arg #%d): Out of memory", + errText, arg); + return 0; + } + for(i=0; i<pointerNumber; i++) + memcpy(buffer+i*setLenBytes, + data[i], setLenBytes); + + res = jnitoolsNativeArray2JavaArray (env, jbt, + buffer, dataArrayLen, + errText, arg); + free(buffer); + return res; +} + +void LIBAPIENTRY jnitoolsReleaseJavaArray2NativeArray (JNIEnv *env, jarray arr, JavaBasicType jbt, + void *data, int dataArrayLen, + const char * errText, int arg) +{ + int len = (*env)->GetArrayLength(env, arr); + int lenb = 0; + void * arrdata = 0; + + if(!isinit && init(env)) isinit=1; + + if(len!=dataArrayLen) + { + jnitoolsThrowByName(env, "java/lang/IllegalArgumentException", + "%s(arg #%d): Array-Length differs of Java-Callback input(%d) vs output(%d)", errText, arg, dataArrayLen, len); + return; + } + + arrdata = (void *) (*env)->GetPrimitiveArrayCritical(env, arr, 0); + + switch(jbt) + { + case T_BOOLEAN_ARRAY: + lenb = len*sizeof(jboolean); + break; + case T_BYTE_ARRAY: + lenb = len*sizeof(jbyte); + break; + case T_CHAR_ARRAY: + lenb = len*sizeof(jchar); + break; + case T_SHORT_ARRAY: + lenb = len*sizeof(jshort); + break; + case T_INT_ARRAY: + lenb = len*sizeof(jint); + break; + case T_LONG_ARRAY: + lenb = len*sizeof(jlong); + break; + case T_FLOAT_ARRAY: + lenb = len*sizeof(jfloat); + break; + case T_DOUBLE_ARRAY: + lenb = len*sizeof(jdouble); + break; + default: + jnitoolsThrowByName(env, "java/lang/IllegalArgumentException", + "%s(arg #%d): Type is not an array", + errText, arg); + } + memcpy (data, arrdata, lenb); + (*env)->ReleasePrimitiveArrayCritical(env, arr, arrdata, JNI_ABORT); +} + +void LIBAPIENTRY jnitoolsReleaseJavaArray2NativeArrayPtr (JNIEnv *env, + jarray arr, + JavaBasicType jbt, + void *data[/*pointerNumber*/], + int pointerNumber, + int dataArrayLen, + const char * errText, + int arg) +{ + int len = (*env)->GetArrayLength(env, arr); + unsigned char * arrdata = 0; + int i; + int setLenElems = dataArrayLen/pointerNumber; + int setLenBytes = 0; + + if(!isinit && init(env)) isinit=1; + + if(len!=dataArrayLen) + { + jnitoolsThrowByName(env, "java/lang/IllegalArgumentException", + "%s(arg #%d): Array-Length differs of Java-Callback input(%d) vs output(%d)", errText, arg, dataArrayLen, len); + return; + } + + arrdata = (unsigned char *) + (*env)->GetPrimitiveArrayCritical(env, arr, 0); + + switch(jbt) + { + case T_BOOLEAN_ARRAY: + setLenBytes = setLenElems * sizeof(jboolean); + break; + case T_BYTE_ARRAY: + setLenBytes = setLenElems * sizeof(jbyte); + break; + case T_CHAR_ARRAY: + setLenBytes = setLenElems * sizeof(jchar); + break; + case T_SHORT_ARRAY: + setLenBytes = setLenElems * sizeof(jshort); + break; + case T_INT_ARRAY: + setLenBytes = setLenElems * sizeof(jint); + break; + case T_LONG_ARRAY: + setLenBytes = setLenElems * sizeof(jlong); + break; + case T_FLOAT_ARRAY: + setLenBytes = setLenElems * sizeof(jfloat); + break; + case T_DOUBLE_ARRAY: + setLenBytes = setLenElems * sizeof(jdouble); + break; + default: + jnitoolsThrowByName(env, "java/lang/IllegalArgumentException", + "%s(arg #%d): Type is not an array", errText, arg); + } + for(i=0; i<pointerNumber; i++) + memcpy(data[i], arrdata+i*setLenBytes, + setLenBytes); + (*env)->ReleasePrimitiveArrayCritical(env, arr, arrdata, JNI_ABORT); +} + + +void * LIBAPIENTRY jnitoolsCreateNativeArray (JavaBasicType jbt, int dataArrayLen, const char * errText) +{ + void * arrdata = 0; + + (void)errText; + + switch(jbt) + { + case T_BOOLEAN_ARRAY: + arrdata = calloc(dataArrayLen, sizeof(int)); + break; + case T_BYTE_ARRAY: + arrdata = calloc(dataArrayLen, sizeof(char)); + break; + case T_CHAR_ARRAY: + arrdata = calloc(dataArrayLen, sizeof(char)); + break; + case T_SHORT_ARRAY: + arrdata = calloc(dataArrayLen, sizeof(short)); + break; + case T_INT_ARRAY: + arrdata = calloc(dataArrayLen, sizeof(int)); + break; + case T_LONG_ARRAY: + arrdata = calloc(dataArrayLen, sizeof(long)); + break; + case T_FLOAT_ARRAY: + arrdata = calloc(dataArrayLen, sizeof(float)); + break; + case T_DOUBLE_ARRAY: + arrdata = calloc(dataArrayLen, sizeof(double)); + break; + default: + return 0; + } + return arrdata; +} + |