本站首页    管理页面    写新日志    退出


«October 2025»
1234
567891011
12131415161718
19202122232425
262728293031


公告

戒除浮躁,读好书,交益友


我的分类(专题)

日志更新

最新评论

留言板

链接

Blog信息
blog名称:邢红瑞的blog
日志总数:523
评论数量:1142
留言数量:0
访问次数:9720515
建立时间:2004年12月20日




[jvm]jni中要注意的问题 
原创空间,  软件技术,  电脑与网络

邢红瑞 发表于 2005/2/11 15:42:24

JNI 的类型和数据结构Java 类型  本地类型  说明 boolean  jboolean  无符号,8 位 byte     jbyte  无符号,8 位 char     jchar  无符号,16 位 short    jshort  有符号,16 位 int      jint  有符号,32 位 long     jlong  有符号,64 位 float    jfloat  32 位 double    jdouble  64 位 void     void  N/A由于JVM中,使用统一的UTF-8编码,java传入的String参数,在c文件中被jni转换为jstring的数据类型,在c文件中声明char* psz,然后psz = (char*)(*env)->GetStringUTFChars(env, jstring, NULL);c++的操作简单些,env->GetStringUTFChars( jstring, NULL);注意使用完后,运行(*env)->ReleaseStringUTFChars(env, jstring, psz);将一个c的字符串转为jstring, static char lastfile[80];   JNIEXPORT jstring JNICALL Java_ReadFile_lastFile    (JNIEnv *env, jobject jobj) {     return((*env)->NewStringUTF(env, lastfile));  }例子JNIEXPORT jstring JNICALLJava_Prompt_getLine(JNIEnv *env, jobject obj, jstring prompt){char buf[128];const jbyte *str;str = (*env)->GetStringUTFChars(env, prompt, NULL);if (str == NULL) {return NULL; /* OutOfMemoryError already thrown */}printf("%s", str);(*env)->ReleaseStringUTFChars(env, prompt, str);/* We assume here that the user does not type more than* 127 characters */scanf("%s", buf);return (*env)->NewStringUTF(env, buf);}如果使用Unicode编码,不需要使用UTF-8处理,使用如下方法JNIEXPORT jbyteArray JNICALL Java_ReadFile_loadFile    (JNIEnv * env, jobject jobj, jstring name) {      caddr_t m;      jbyteArray jb;      struct stat finfo;      jboolean iscopy;      const jchar *mfile = (*env)->GetStringChars(env,   name, &iscopy);  //...      (*env)->ReleaseStringChars(env, name, mfile);传递Arrayboolean  public static void setArray( boolean[] ba )  {    for( int i=0; i < ba.length; i++ )      ba[i] = true;    setArray0( ba );  }  private static native void setArray0( boolean[] ba ); 布尔型数组被初始化为 true,本地方法将把特定的元素设置为 false。同时,在 Java 源代码中,我们可以更改 main 以使其包含测试代码:     boolean[] ba = new boolean[5];    MyNative.setArray( ba );    for( int i=0; i < ba.length; i++ )      System.out.println( ba[i] ); 在编译源代码并执行 javah 以后,MyNative.h 头文件包含以下的原型: /* * Class:     MyNative * Method:    setArray0 * Signature: ([Z)V */JNIEXPORT void JNICALL Java_MyNative_setArray0  (JNIEnv *, jclass, jbooleanArray); 布尔型数组是作为单个名为 jbooleanArray 的类型创建的。 基本类型有它们自已的数组类型,如 jintArray 和 jcharArray。 非基本类型的数组使用 jobjectArray 类型。下一个示例中包括一个 jobjectArray。这个布尔数组的数组元素是通过 JNI 方法 GetBooleanArrayElements 来访问的。 针对每种基本类型都有等价的方法。这个本地方法是如下实现的: JNIEXPORT void JNICALL Java_MyNative_setArray0  (JNIEnv *env, jclass cls, jbooleanArray ba){  jboolean* pba = (*env)->GetBooleanArrayElements( env, ba, 0 );  jsize len = (*env)->GetArrayLength(env, ba);  int i=0;  // 更改偶数数组元素  for( i=0; i < len; i+=2 )    pba[i] = JNI_FALSE;  (*env)->ReleaseBooleanArrayElements( env, ba, pba, 0 );} 指向布尔型数组的指针可以使用 GetBooleanArrayElements 获得。 数组大小可以用 GetArrayLength 方法获得。使用 ReleaseBooleanArrayElements 方法释放数组。就可以读取和修改数组元素的值了。int 数组 class IntArray {    private native int sumArray(int[] arr);    public static void main(String[] args) {        IntArray p = new IntArray();        int arr[] = new int[10];        for (int i = 0; i < 10; i++) {            arr[i] = i;        }        int sum = p.sumArray(arr);        System.out.println("sum = " + sum);    }     static {        System.loadLibrary("jnistudy");    }} jni的c程序 #include <jni.h>#include <stdio.h>#include "IntArray.h" JNIEXPORT jint JNICALL Java_IntArray_sumArray(JNIEnv *env, jobject obj, jintArray arr){    jint *carr;    jint i, sum = 0;    carr = (*env)->GetIntArrayElements(env, arr, NULL);    if (carr == NULL) {        return 0; /* exception occurred */    }     for (i=0; i<10; i++) {        sum += carr[i];    }     (*env)->ReleaseIntArrayElements(env, arr, carr, 0);    return sum;} GetIntArrayRegion得到数组,ReleaseIntArrayElements释放资源,GetArrayLength得到数组的长度,SetIntArrayRegion修改数组元素的值。 多位int 数组class ObjectArrayTest {    private static native int[][] initInt2DArray(int size);    public static void main(String[] args) {        int[][] i2arr = initInt2DArray(3);        for (int i = 0; i < 3; i++) {            for (int j = 0; j < 3; j++) {                 System.out.print(" " + i2arr[i][j]);            }            System.out.println();        }    }    static {        System.loadLibrary("jnistudy");    }} jni的代码#include <jni.h>#include <stdio.h>#include "ObjectArrayTest.h" JNIEXPORT jobjectArray JNICALLJava_ObjectArrayTest_initInt2DArray(JNIEnv *env,                                   jclass cls,                                   jint size){    jobjectArray result;    int i;    jclass intArrCls = (*env)->FindClass(env, "[I");    if (intArrCls == NULL) {        return NULL; /* exception thrown */    }    result = (*env)->NewObjectArray(env, size, intArrCls, NULL);    if (result == NULL) {        return NULL; /* out of memory error thrown */    }    for (i = 0; i < size; i++) {        jint tmp[256];  /* make sure it is large enough! */        int j;        jintArray iarr = (*env)->NewIntArray(env, size);        if (iarr == NULL) {            return NULL; /* out of memory error thrown */        }        for (j = 0; j < size; j++) {            tmp[j] = i + j;        }        (*env)->SetIntArrayRegion(env, iarr, 0, size, tmp);        (*env)->SetObjectArrayElement(env, result, i, iarr);        (*env)->DeleteLocalRef(env, iarr);    }    return result;}Get/SetObjectArrayElement得到和设置数组的元素的值。传递 Java String 数组 本例将通过最常用的非基本类型,Java String,说明如何访问非基本对象的数组。字符串数组被传递给本地方法,而本地方法只是将它们显示到控制台上。 MyNative 类定义中添加了以下几个方法:   public static void showStrings( String[] sa )  {    showStrings0( sa );  }  private static void showStrings0( String[] sa ); 测试  String[] sa = new String[] { "Hello,", "world!", "JNI", "is", "fun." };  MyNative.showStrings( sa ); c代码中,本地方法分别访问每个元素, JNIEXPORT void JNICALL Java_MyNative_showStrings0  (JNIEnv *env, jclass cls, jobjectArray sa){  int len = (*env)->GetArrayLength( env, sa );  int i=0;  for( i=0; i < len; i++ )  {    jobject obj = (*env)->GetObjectArrayElement(env, sa, i);    jstring str = (jstring)obj;    const char* szStr = (*env)->GetStringUTFChars( env, str, 0 );    printf( "%s ", szStr );    (*env)->ReleaseStringUTFChars( env, str, szStr );  }  printf( "\n" );} 数组元素可以通过 GetObjectArrayElement 访问。 因为返回值是 jstring 类型,所以可以安全地将它从 jobject 类型转换为 jstring 类型。 返回 Java String 数组 在本地代码中创建一个字符串数组并将它返回给 Java 调用者。MyNative.java 中添加了以下几个方法:   public static String[] getStrings()  {    return getStrings0();  }  private static native String[] getStrings0(); 使用showStrings 将 getStrings 的输出显示出来:   MyNative.showStrings( MyNative.getStrings() ); 实现的本地方法返回五个字符串。 JNIEXPORT jobjectArray JNICALL Java_MyNative_getStrings0  (JNIEnv *env, jclass cls){  jstring      str;  jobjectArray args = 0;  jsize        len = 5;  char*        sa[] = { "Hello,", "world!", "JNI", "is", "fun" };  int          i=0;  args = (*env)->NewObjectArray(env, len, (*env)->FindClass(env, "java/lang/String"), 0);  for( i=0; i < len; i++ )  {    str = (*env)->NewStringUTF( env, sa[i] );    (*env)->SetObjectArrayElement(env, args, i, str);  }  return args;} 字符串数组是通过调用 NewObjectArray 创建的,同时传递了 String 类和数组长度两个参数。Java String 是使用 NewStringUTF 创建的。String 元素是使用 SetObjectArrayElement 存入数组中的。 相关的VM的参数-verbose:jni-Xcheck:jni-Djava.library.path=d:\


阅读全文(7429) | 回复(1) | 编辑 | 精华
 


回复:jni中要注意的问题
原创空间,  软件技术,  电脑与网络

yecheng_110(游客)发表评论于2007/6/28 8:56:27

相当不错 谢谢了!


个人主页 | 引用回复 | 主人回复 | 返回 | 编辑 | 删除
 


» 1 »

发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)



站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 4.203 second(s), page refreshed 144810710 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号