JNI类型和Java类型对应关系
| Java类型 | JNI类型 | 真实C++类型 |
|---|---|---|
| boolean | jboolean | uint8_t,unsigned char |
| byte | jbyte | int8_t,signed char |
| char | jchar | uint16_t,unsigned short |
| short | jshort | int16_t,short |
| int | jint | int32_t,int |
| long | jlong | int64_t,long long |
| float | jfloat | float |
| double | jdouble | double |
| Object | jobject | c++ class |
| Class | jclass | c++ class,继承jobject |
| String | jstring | c++ class,继承jobject |
| boolean[] | jbooleanArray | c++ class,继承jarray和jobject |
| byte[] | jbyteArray | c++ class,继承jarray和jobject |
| char[] | jcharArray | c++ class,继承jarray和jobject |
| short[] | jshortArray | c++ class,继承jarray和jobject |
| int[] | jintArray | c++ class,继承jarray和jobject |
| long[] | jlongArray | c++ class,继承jarray和jobject |
| float[] | jfloatArray | c++ class,继承jarray和jobject |
| double[] | jdoubleArray | c++ class,继承jarray和jobject |
| Object[] | jobjectArray | c++ class,继承jarray和jobject |
| Class[] | jobjectArray | c++ class,继承jarray和jobject |
| String[] | jobjectArray | c++ class,继承jarray和jobject |
JNI类型和方法签名
在C++代码中,可以通过反射获取Java中的方法和类型
Java中的每个类型和方法,都对应一个唯一字符串,这个就是签名
| Java类型 | 签名 |
|---|---|
| boolean | Z |
| byte | B |
| char | C |
| short | S |
| int | I |
| long | L |
| float | F |
| double | D |
| Object | L+包名+分号 |
| [] | [+类型签名 |
| [][] | [[+类型签名 |
| 方法 | (参数签名)+返回值签名 |
签名示例如下
| Java类型 | 签名 |
|---|---|
| String | Ljava/lang/String; |
| Object | Ljava/lang/Object; |
| String[] | [Ljava/lang/String; |
| int func(int i, Object object) | (ILjava/lang/Object;)I |
C++接收和创建Java类对象
//通过JNI复制一个Java对象
native Point native_copy_object(Point object);
//调用JNI方法复制对象
Point srcObject = new Point(5, 10);
Point dstObject = native_copy_object(srcObject);
//C++实现JNI函数
extern "C" JNIEXPORT jobject JNICALL
Java_easing_android_media_MediaPlayer_native_1copy_1object(JNIEnv *env, jobject obj, jobject srcObject) {
//找到Point对应的Class
jclass dstClazz = env->FindClass("android/graphics/Point");
//获取srcObject的字段值
jfieldID xFieldId = env->GetFieldID(dstClazz, "x", "I");
jfieldID yFieldId = env->GetFieldID(dstClazz, "y", "I");
jint x = env->GetIntField(srcObject, xFieldId);
jint y = env->GetIntField(srcObject, yFieldId);
//创建一个新的Point对象
jobject dstObject = env->AllocObject(dstClazz);
//拷贝srcObject的字段给dstObject
env->SetIntField(dstObject, xFieldId, x);
env->SetIntField(dstObject, yFieldId, y);
//返回新的Point给Java
return dstObject;
}
Java接收和创建C++类对象
C++对象是没法传递给Java层的
因为在C++中,有jobject对应Java中的类型,但在Java中,却没有数据类型能够对应C++中的类类型
但我们却可以通过方法封装,快速将C++对象转为Java对象,再传递给Java,或是将收到的Java对象,快速转为C++对象
struct Point {
public:
int x;
int y;
//从JavaObject创建一个C++Object
static Point *fromJavaObject(JNIEnv *&env, jobject &interface, jobject &javaObject) {
Point *point = new Point();
jclass clazz = env->FindClass("android/graphics/Point");
jfieldID xFieldId = env->GetFieldID(clazz, "x", "I");
jfieldID yFieldId = env->GetFieldID(clazz, "y", "I");
point->x = env->GetIntField(javaObject, xFieldId);
point->y = env->GetIntField(javaObject, yFieldId);
return point;
}
//从C++Object创建一个JavaObject
static jobject toJavaObject(JNIEnv *&env, jobject &interface, Point *&cppObject) {
Point *point = new Point();
jclass clazz = env->FindClass("android/graphics/Point");
jfieldID xFieldId = env->GetFieldID(clazz, "x", "I");
jfieldID yFieldId = env->GetFieldID(clazz, "y", "I");
jobject javaObject = env->AllocObject(clazz);
env->SetIntField(javaObject, xFieldId, cppObject->x);
env->SetIntField(javaObject, yFieldId, cppObject->y);
return javaObject;
}
};
