JNI编程参考备忘----基本类型
来源:互联网 发布:网络经常听的dj 编辑:程序博客网 时间:2024/05/14 10:44
在Java编程中,本地方法的声明一般如下:
private native String getLine(String prompt);
跟其他普通的Java类的方法相比,只有声明,没有方法体,且必须带一个native修饰符。另外,在类中,通过静态代码初始化的方法,调用System.loadLibrary(...)方法,加载本地方法的实现——JNI库,如下为Java本地方法使用的一个范例:
public class Prompt implements TestCase{ //native method that prints a prompt and reads a line private native String getLine(String prompt); static { String path = System.getProperty("java.library.path"); System.loadLibrary("Prompt"); } @Override public void doTest() { String input = this.getLine("Please input something and enter return"); System.out.println("User Typed: " + input); } }
如上所示,系统将加载libPrompt.so库。在JNI本地实现代码中,对应的方法声明如下:
JNIEXPORT jstring JNICALL Java_com_fyj_test_Prompt_getLine
(JNIEnv *, jobject, jstring);
第一个参数JNIEnv是一个接口指针,它指向了一个位置,该位置是一个指针数组,它包含了许多JNI函数的指针。根据本地方法的声明方式,如果声明了类的静态方法,则第二个参数是该类的一个引用,否则这个参数就是对该类实例的一个引用,相当于this指针。
基本类型
在Java中,有两种类型,一种是初始类型如int,float,以及char,还有一种是引用类型如类,实例以及数组。JNI对这两种类型的处理不一样。对于初始类型,与C/C++编程语言类型的映射很简单,如int对应jint, float对应jfloat等等。而对于引用类型,JNI则当作不透明引用,即C的指针类型,它们指向Java虚拟机的内部数据结构。本地方法必须通过合适的JNI函数来操控它们。例如,对于java.lang.String类,它对应的C/C++类型为jstring。本地代码要访问这个字符串的内容必须通过调用JNI函数如GetStringUTFChars。
字符串访问
JNI层本地代码对应的数据类型为jstring,但是,不能直接当作普通的C字符串,必须使用合适的JNI函数来将jstring对象转换为C/C++字符串。JNI支持Unicode和UTF-8字符串与jstring对象的双向转换。示例代码如下:
JNIEXPORT jstring JNICALL Java_com_fyj_test_Prompt_getLine (JNIEnv *env, jobject obj, jstring prompt){#if 0 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);#endif /* assume the prompt string and user input has less than 128 characters */ char outbuf[128], inbuf[128]; int len = (*env)->GetStringLength(env, prompt); (*env)->GetStringUTFRegion(env, prompt, 0, len, outbuf); printf("%s", outbuf); scanf("%s", inbuf); return (*env)->NewStringUTF(env, inbuf);}
字符串相关的JNI函数如下所示:
JNI Function
Description
Since
GetStringChars
ReleaseStringChars
Obtains or releases a pointer to the contents of a string in Unicode format. May return a copy of the string.
JDK1.1
GetStringUTFChars
ReleaseStringUTFChars
Obtains or releases a pointer to the contents of a string in UTF-8 format. May return a copy of the string.
JDK1.1
GetStringLength
Returns the number of Unicode characters in the string.
JDK1.1
GetStringUTFLength
Returns the number of bytes needed (not including the trailing 0) to represent a string in the UTF-8 format.
JDK1.1
NewString
Creates a java.lang.String instance that contains the same sequence of characters as the given Unicode C string.
JDK1.1
NewStringUTF
Creates a java.lang.String instance that contains the same sequence of characters as the given UTF-8 encoded C string.
JDK1.1
GetStringCritical
ReleaseStringCritical
Obtains a pointer to the contents of a string in Unicode format. May return a copy of the string. Native code must not block between a pair of Get/ReleaseStringCritical calls.
JDK1.1
GetStringRegion
SetStringRegion
Copies the contents of a string to or from a preallocated C buffer in the Unicode format.
Java 2
SDK1.2
GetStringUTFRegion
SetStringUTFRegion
Copies the content of a string to or from a preallocated C buffer in the UTF-8 format.
Java 2
SDK 1.2
初始类型数组访问
初始数据类型的数组访问与对象类型的数组访问又有不同。访问初始类型的数据与访问字符串一样,也需要使用JNI函数进行转换。
如下代码所示:
JNIEXPORT jint JNICALL Java_com_fyj_test_IntArray_sumArray (JNIEnv *env, jobject obj, jintArray arr){#if 0 jint buf[100]; jint i, sum = 0; (*env)->GetIntArrayRegion(env, arr, 0, 100, buf); for (i = 0; i < 100; i++) { sum += buf[i]; } return sum;#endif jint *carr; jint i, sum = 0; carr = (*env)->GetIntArrayElements(env, arr, NULL); if (carr == NULL) { return 0; /* exception occurred */ } for (i=0; i<100; i++) { sum += carr[i]; } (*env)->ReleaseIntArrayElements(env, arr, carr, 0); return sum;}
相关的JNI函数如下:
JNI Function
Description
Since
Get<Type>ArrayRegion
Set<Type>ArrayRegion
Copies the contents of primitive arrays to or from a pre-allocated C buffer.
JDK 1.1
Get<Type>ArrayElements
Release<Type>ArrayElements
Obtains a pointer to the contents of a primitive array.
May return a copy of the array.
JDK 1.1
GetArrayLength
Returns the number of elements in the array.
JDK 1.1
New<Type>Array
Creates an array with the given length.
JDK 1.1
GetPrimitiveArrayCritical
ReleasePrimitiveArrayCritica
Obtains or releases a pointer to the contents of a primitive array. May disable garbage collection, or return a copy of the array.
Java 2
SDK 1.2
对象类型数组访问
访问对象类型数组需要使用一组不同的JNI函数:
GetObjectArrayElement:返回某个下标处的元素。
SetObjectArrayElement:设置某个下标处的元素。
不同于初始类型数组,你不能一次获取整个对象元素或复制多个对象元素。
由于字符串和数组也属于引用类型,所以可以使用上述函数访问字符串数组或数组的数组。代码示例如下:
JNIEXPORT jobjectArray JNICALL Java_com_fyj_test_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;}
- JNI编程参考备忘----基本类型
- JNI编程参考备忘----成员变量和方法
- JNI编程指南-第三章 基本类型、字符串、数组
- JNI基本编程
- JNI 学习篇--基本类型
- JNI由浅入深_5_基本类型应用
- JNI之C语言(二)-- 基本类型
- jni中的基本类型、字符串和数组
- java 编程-------基本类型
- CPP学习备忘[1] 基本编程语句
- 基本类型与自定义类型 的内存对应问题 (备忘)
- Android JNI编程之基础学习(一) 认识c语言的基本类型,输出输入函数
- Android JNI编程之基础学习(一) 认识c语言的基本类型,输出输入函数
- Android jni/ndk编程四:jni引用类型
- JNI 学习备忘
- JNI备忘API
- android--JNI 实例备忘
- jni问题备忘
- 关于java的equals和hashcode方法
- redis常用命令
- 在C#中用MySql.Data.MySqlClient连接MySql
- 教您烧香祈福的正确方法
- 求三角形
- JNI编程参考备忘----基本类型
- POJ 3176(Cow Bowling )(就是简单的数塔,动态规划)
- 联网的桥梁——C/S
- 第12周项目3 用递归方法求解(6)
- 在EditPlus里配置Java环境
- 第十二周项目一(3-2)
- 代理传值
- 第一天:安装虚拟机(vm9)和linux(ubuntu12.04),以及通过串口连接开发板(Tiny 6410
- Ubuntu14.04的NFS开发环境配置