(一)JNI基本概念
1. 基本概念:
首先,注意:C和C++在调用JNI时候方法是不一样的
注意看下面两个的区别:
C++
#include <jni.h> #include <string> extern "C" JNIEXPORT jstring JNICALL Java_android_1serialport_1api_sample_MainActivity_stringFromJNI( JNIEnv *env, jobject /* this */) { std::string hello = "Hello from C++"; return env->NewStringUTF(hello.c_str()); }
C:
#include <string.h> #include <jni.h> JNIEXPORT jobject JNICALL Java_android_1serialport_1api_SerialPort_open (JNIEnv *env, jclass thiz, jstring path, jint baudrate, jint flags) { (*env)->ReleaseStringUTFChars(env, path, path_utf);
return mFileDescriptor; }
区别:
C | C++ |
(*env)->xxx | env->xxx |
#include<string.h> | #include<string> |
基本数据类型: boolean/char/byte/short/int/long/double/float/
//引用数据类型则不能直接使用,需要根据JNI函数进行相应的转换后,才能使用
引用数据类型: object/class/string/byte[]/short[]/int[]/long[]/...
描述符(注意:除了基本类型,其他都有;冒号)
1. 类描述符 String:/java/lang/String;
2. 数组类型描述符
3.域描述符:其实就是属性或者数据描述符
1). 基本数据类型描述符 Z/B/C/S
2). 引用数据类型描述符 数组:[I/[F:一维数组 [[i:二维数组 [Ljava/lang/Object:String[]
3). 方法描述符:
String test(): ()Ljava/lang/String; (这里的;不可少)
void set(byte[] bytes): ([B)V (这里的;不可少)
int f(int i, Object object): (ILjava/lang/Object)I
C-->JAVA:
创建一个对象的方法
1. 加载类:(FindClass)
2. 找到该类的构造方法的id(GetMethodID(env,1中找到的类,"<init>","()V"))
3. 创建该类一个新的对象(NewObject(env, 1中找到的类, 2中找到的构造方法))
调用一个对象中的属性
1. 找到该对象的类(FindClass)
2. 找到类中的属性ID(GetFieldID(env, 1中的类, 属性名, 属性描述符))
3. 得到该属性(GetIntField(env, 对象, 2中的属性ID))
调用一个对象中的方法
1. 找到该对象的类(GetObjectClass(env, 这个对象))
2. 找到类中的方法ID
3. 设置该对象的方法
2. 数据类型
1. 基本类型:
2. 引用类型:
引用数据类型则不能直接使用,需要根据JNI函数进行相应的转换后,才能使用
3. 描述符
1. 类描述符
类描述符是类的完整名称(包名+类名),将原来的 . 分隔符换成 / 分隔符。
例如:在java代码中的java.lang.String类的类描述符就是java/lang/String
其实,在实践中,我发现可以直接用该类型的域描述符取代,也是可以成功的。
例如: jclass intArrCls = env->FindClass("java/lang/String")
等同于 jclass intArrCls = env->FindClass("Ljava/lang/String;")
2. 属性描述符
JNI函数分为:类操作、异常操作、全局或局部引用、对象操作、字符串操作、访问对象的属性和方法、注册本地方法。
4. 操作方法
创建一个对象的方法
1. 加载类:(FindClass)
2. 找到该类的构造方法的id(GetMethodID(env,1中找到的类,"<init>","()V"))
3. 创建该类一个新的对象(NewObject(env, 1中找到的类, 2中找到的构造方法))
调用一个对象中的属性
1. 找到该对象的类(FindClass)
2. 找到类中的属性ID(GetFieldID(env, 1中的类, 属性名, 属性描述符))
3. 得到该属性(GetIntField(env, 对象, 2中的属性ID))
调用一个对象中的方法
1. 找到该对象的类(GetObjectClass(env, 这个对象))
2. 找到类中的方法ID
3. 设置该对象的方法
参考资料:
http://blog.csdn.net/qinjuning/article/details/7595104/
http://blog.csdn.net/qinjuning/article/details/7599796