⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dispatch.c

📁 学习JAVA编程的示例
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * @(#)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 + -