« | October 2025 | » | 日 | 一 | 二 | 三 | 四 | 五 | 六 | | | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | | |
| 公告 |
戒除浮躁,读好书,交益友 |
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:\ |
|
回复:jni中要注意的问题 原创空间, 软件技术, 电脑与网络
yecheng_110(游客)发表评论于2007/6/28 8:56:27 |
|
» 1 »
|