📄 dispatch.c
字号:
/*
* @(#)dispatch.c 1.9 98/03/22
*
* Copyright (c) 1998 Sun Microsystems, Inc. All Rights Reserved.
*
* See also the LICENSE file in this distribution.
*/
/*
* JNI native methods supporting the infrastructure for shared
* dispatchers. Includes native methods for classes CPtr, CFunc, and
* CMalloc.
*/
#ifdef SOLARIS2
#include <dlfcn.h>
#define LOAD_LIBRARY(name) dlopen(name, RTLD_LAZY)
#define FIND_ENTRY(lib, name) dlsym(lib, name)
#endif
#ifdef WIN32
#include <windows.h>
#define LOAD_LIBRARY(name) LoadLibrary(name)
#define FIND_ENTRY(lib, name) GetProcAddress(lib, name)
#endif
#include <stdlib.h>
#include <string.h>
#include <jni.h>
#include "CPtr.h"
#include "CFunc.h"
#include "CMalloc.h"
/* Global references to frequently used classes and objects */
static jclass classString;
static jclass classInteger;
static jclass classFloat;
static jclass classDouble;
static jclass classCPtr;
static jobject objectCPtrNULL;
/* Cached field and method IDs */
static jmethodID String_getBytes_ID;
static jmethodID String_init_ID;
static jfieldID Integer_value_ID;
static jfieldID Float_value_ID;
static jfieldID Double_value_ID;
static jfieldID CPtr_peer_ID;
/* Forward declarations */
static void throwByName(JNIEnv *env, const char *name, const char *msg);
static char * getJavaString(JNIEnv *env, jstring jstr);
static jstring newJavaString(JNIEnv *env, const char *str);
static jobject makeCPtr(JNIEnv *env, void *p);
/********************************************************************/
/* Native methods of class CFunc */
/********************************************************************/
/* These are the set of types CFunc can handle now */
typedef enum {
TY_CPTR = 0,
TY_INTEGER,
TY_FLOAT,
TY_DOUBLE,
TY_DOUBLE2,
TY_STRING,
} ty_t;
/* represent a machine word */
typedef union {
jint i;
jfloat f;
void *p;
} word_t;
/* A CPU-dependent assembly routine that passes the arguments to C
* stack and invoke the function.
*/
extern void
asm_dispatch(void *func, int nwords, word_t *c_args, ty_t ty, jvalue *resP);
/* invoke the real native function */
static void
dispatch(JNIEnv *env, jobject self, jobjectArray arr, ty_t ty, jvalue *resP)
{
#define MAX_NARGS 32
int i, nargs, nwords;
void *func;
char argTypes[MAX_NARGS];
word_t c_args[MAX_NARGS * 2];
nargs = (*env)->GetArrayLength(env, arr);
if (nargs > MAX_NARGS) {
throwByName(env, "java/lang/IllegalArgumentException",
"too many arguments");
return;
}
func = (void *)(*env)->GetLongField(env, self, CPtr_peer_ID);
for (nwords = 0, i = 0; i < nargs; i++) {
jobject arg = (*env)->GetObjectArrayElement(env, arr, i);
if (arg == NULL) {
throwByName(env, "java/lang/NullPointerException",
"bad argument");
goto cleanup;
}
if ((*env)->IsInstanceOf(env, arg, classInteger)) {
c_args[nwords].i = (*env)->GetIntField(env, arg, Integer_value_ID);
argTypes[nwords++] = TY_INTEGER;
} else if ((*env)->IsInstanceOf(env, arg, classCPtr)) {
c_args[nwords].p =
(void *)(*env)->GetLongField(env, arg, CPtr_peer_ID);
argTypes[nwords++] = TY_CPTR;
} else if ((*env)->IsInstanceOf(env, arg, classString)) {
if ((c_args[nwords].p = getJavaString(env, arg)) == 0) {
goto cleanup;
}
argTypes[nwords++] = TY_STRING;
} else if ((*env)->IsInstanceOf(env, arg, classFloat)) {
c_args[nwords].f = (*env)->GetFloatField(env, arg, Float_value_ID);
argTypes[nwords++] = TY_FLOAT;
} else if ((*env)->IsInstanceOf(env, arg, classDouble)) {
*(jdouble *)(c_args + nwords) =
(*env)->GetDoubleField(env, arg, Double_value_ID);
argTypes[nwords] = TY_DOUBLE;
/* harmless with 64-bit machines*/
argTypes[nwords + 1] = TY_DOUBLE2;
/* make sure things work on 64-bit machines */
nwords += sizeof(jdouble) / sizeof(word_t);
} else {
throwByName(env, "java/lang/IllegalArgumentException",
"unrecognized argument type");
goto cleanup;
}
(*env)->DeleteLocalRef(env, arg);
}
asm_dispatch(func, nwords, c_args, ty, resP);
cleanup:
for (i = 0; i < nwords; i++) {
if (argTypes[i] == TY_STRING) {
free(c_args[i].p);
}
}
return;
}
/*
* Class: CFunc
* Method: callCPtr
* Signature: ([Ljava/lang/Object;)LCPtr;
*/
JNIEXPORT jobject JNICALL
Java_CFunc_callCPtr(JNIEnv *env, jobject self, jobjectArray arr)
{
jvalue result;
dispatch(env, self, arr, TY_CPTR, &result);
if ((*env)->ExceptionOccurred(env)) {
return NULL;
}
return makeCPtr(env, (void *)result.j);
}
/*
* Class: CFunc
* Method: callDouble
* Signature: ([Ljava/lang/Object;)D
*/
JNIEXPORT jdouble JNICALL
Java_CFunc_callDouble(JNIEnv *env, jobject self, jobjectArray arr)
{
jvalue result;
dispatch(env, self, arr, TY_DOUBLE, &result);
return result.d;
}
/*
* Class: CFunc
* Method: callFloat
* Signature: ([Ljava/lang/Object;)F
*/
JNIEXPORT jfloat JNICALL
Java_CFunc_callFloat(JNIEnv *env, jobject self, jobjectArray arr)
{
jvalue result;
dispatch(env, self, arr, TY_FLOAT, &result);
return result.f;
}
/*
* Class: CFunc
* Method: callInt
* Signature: ([Ljava/lang/Object;)I
*/
JNIEXPORT jint JNICALL
Java_CFunc_callInt(JNIEnv *env, jobject self, jobjectArray arr)
{
jvalue result;
dispatch(env, self, arr, TY_INTEGER, &result);
return result.i;
}
/*
* Class: CFunc
* Method: callVoid
* Signature: ([Ljava/lang/Object;)V
*/
JNIEXPORT void JNICALL
Java_CFunc_callVoid(JNIEnv *env, jobject self, jobjectArray arr)
{
jvalue result;
dispatch(env, self, arr, TY_INTEGER, &result);
}
/*
* Class: CFunc
* Method: find
* Signature: (Ljava/lang/String;Ljava/lang/String;)J
*/
JNIEXPORT jlong JNICALL Java_CFunc_find
(JNIEnv *env, jobject self, jstring lib, jstring fun)
{
void *handle;
void *func;
char *libname = 0;
char *funname = 0;
if ((libname = getJavaString(env, lib)) == 0) {
goto ret;
}
if ((funname = getJavaString(env, fun)) == 0) {
goto ret;
}
if ((handle = (void *)LOAD_LIBRARY(libname)) == NULL) {
throwByName(env, "java/lang/UnsatisfiedLinkError", libname);
goto ret;
}
if ((func = (void *)FIND_ENTRY(handle, funname)) == NULL) {
throwByName(env, "java/lang/UnsatisfiedLinkError", funname);
goto ret;
}
ret:
free(libname);
free(funname);
return (jlong)func;
}
/********************************************************************/
/* Native methods of class CPtr */
/********************************************************************/
/*
* Class: CPtr
* Method: initIDs
* Signature: (LCPtr;)I
*/
JNIEXPORT jint JNICALL
Java_CPtr_initIDs(JNIEnv *env, jclass cls, jobject nullCPtr)
{
objectCPtrNULL = (*env)->NewGlobalRef(env, nullCPtr);
if (objectCPtrNULL == NULL) return 0;
classString = (*env)->FindClass(env, "java/lang/String");
if (classString == NULL) return 0;
classString = (*env)->NewGlobalRef(env, classString);
if (classString == NULL) return 0;
classInteger = (*env)->FindClass(env, "java/lang/Integer");
if (classInteger == NULL) return 0;
classInteger = (*env)->NewGlobalRef(env, classInteger);
if (classInteger == NULL) return 0;
classFloat = (*env)->FindClass(env, "java/lang/Float");
if (classFloat == NULL) return 0;
classFloat = (*env)->NewGlobalRef(env, classFloat);
if (classFloat == NULL) return 0;
classDouble = (*env)->FindClass(env, "java/lang/Double");
if (classDouble == NULL) return 0;
classDouble = (*env)->NewGlobalRef(env, classDouble);
if (classDouble == NULL) return 0;
classCPtr = (*env)->NewGlobalRef(env, cls);
if (classCPtr == NULL) return 0;
String_getBytes_ID =
(*env)->GetMethodID(env, classString, "getBytes", "()[B");
if (String_getBytes_ID == NULL) return 0;
String_init_ID = (*env)->GetMethodID(env, classString, "<init>", "([B)V");
if (String_init_ID == NULL) return 0;
Integer_value_ID = (*env)->GetFieldID(env, classInteger, "value", "I");
if (Integer_value_ID == NULL) return 0;
Float_value_ID = (*env)->GetFieldID(env, classFloat, "value", "F");
if (Float_value_ID == NULL) return 0;
Double_value_ID = (*env)->GetFieldID(env, classDouble, "value", "D");
if (Double_value_ID == NULL) return 0;
CPtr_peer_ID = (*env)->GetFieldID(env, classCPtr, "peer", "J");
return sizeof(void *);
}
/*
* Class: CPtr
* Method: copyIn
* Signature: (I[BII)V
*/
JNIEXPORT void JNICALL Java_CPtr_copyIn__I_3BII
(JNIEnv *env, jobject self, jint boff, jbyteArray arr, jint off, jint n)
{
jbyte *peer = (jbyte *)(*env)->GetLongField(env, self, CPtr_peer_ID);
(*env)->GetByteArrayRegion(env, arr, off, n, peer + boff);
}
/*
* Class: CPtr
* Method: copyIn
* Signature: (I[CII)V
*/
JNIEXPORT void JNICALL Java_CPtr_copyIn__I_3CII
(JNIEnv *env, jobject self, jint boff, jcharArray arr, jint off, jint n)
{
jchar *peer = (jchar *)(*env)->GetLongField(env, self, CPtr_peer_ID);
(*env)->GetCharArrayRegion(env, arr, off, n, peer + boff);
}
/*
* Class: CPtr
* Method: copyIn
* Signature: (I[DII)V
*/
JNIEXPORT void JNICALL Java_CPtr_copyIn__I_3DII
(JNIEnv *env, jobject self, jint boff, jdoubleArray arr, jint off, jint n)
{
jdouble *peer = (jdouble *)(*env)->GetLongField(env, self, CPtr_peer_ID);
(*env)->GetDoubleArrayRegion(env, arr, off, n, peer + boff);
}
/*
* Class: CPtr
* Method: copyIn
* Signature: (I[FII)V
*/
JNIEXPORT void JNICALL Java_CPtr_copyIn__I_3FII
(JNIEnv *env, jobject self, jint boff, jfloatArray arr, jint off, jint n)
{
jfloat *peer = (jfloat *)(*env)->GetLongField(env, self, CPtr_peer_ID);
(*env)->GetFloatArrayRegion(env, arr, off, n, peer + boff);
}
/*
* Class: CPtr
* Method: copyIn
* Signature: (I[III)V
*/
JNIEXPORT void JNICALL Java_CPtr_copyIn__I_3III
(JNIEnv *env, jobject self, jint boff, jintArray arr, jint off, jint n)
{
jint *peer = (jint *)(*env)->GetLongField(env, self, CPtr_peer_ID);
(*env)->GetIntArrayRegion(env, arr, off, n, peer + boff);
}
/*
* Class: CPtr
* Method: copyIn
* Signature: (I[JII)V
*/
JNIEXPORT void JNICALL Java_CPtr_copyIn__I_3JII
(JNIEnv *env, jobject self, jint boff, jlongArray arr, jint off, jint n)
{
jlong *peer = (jlong *)(*env)->GetLongField(env, self, CPtr_peer_ID);
(*env)->GetLongArrayRegion(env, arr, off, n, peer + boff);
}
/*
* Class: CPtr
* Method: copyIn
* Signature: (I[SII)V
*/
JNIEXPORT void JNICALL Java_CPtr_copyIn__I_3SII
(JNIEnv *env, jobject self, jint boff, jshortArray arr, jint off, jint n)
{
jshort *peer = (jshort *)(*env)->GetLongField(env, self, CPtr_peer_ID);
(*env)->GetShortArrayRegion(env, arr, off, n, peer + boff);
}
/*
* Class: CPtr
* Method: copyOut
* Signature: (I[BII)V
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -