![438cc4d23efb37769e35ce14d50b2a75.png](https://i-blog.csdnimg.cn/blog_migrate/845fd3131099038c2169966fbaa14935.jpeg)
Java的应用广,C++性能强,JNI就是两者连接的桥梁。一个安卓应用,做交互肯定是java,但是底层的音视频处理、机器学习,就必须要靠C++这个强悍的发动机。本文我们就一起做个改装,给java装个好发动机。
1. 在C++中读取和创建java String
extern "C"
JNIEXPORT jstring JNICALL
Java_com_example_myapplication_JniRobotBCActivity_howToSpeakChinese(JNIEnv *env, jobject thiz,
jstring english) {
//1: java字符串转成C++字符串
jboolean isTrue;
char* strNative;
strNative =(char *)(env->GetStringUTFChars(english, &isTrue));
//2:做一些处理操作
char* china=":你好";
strcat( strNative,china);
//3:再把字符串转回java字符串
env->ReleaseStringUTFChars(english,strNative);
jstring javaString= env->NewStringUTF(strNative);
return javaString;
}
如果是c++的字符串,需要转成c风格的char*
std::string str="hello";
jstring javaString= env->NewStringUTF(str.c_str());
2.在C++中创建Java对象
//(1)根据java类的文件目录找到该类
jclass robotClass=env->FindClass("com/example/myapplication/Robot");
//(2) 获取该类的构造方法ID
jmethodID robotConstruct=env->GetMethodID(robotClass,"<init>","(Ljava/lang/String;ILjava/util/HashMap;)V");
// "<init>"表示构造方法
//"(Ljava/lang/String;ILjava/util/HashMap;)V"是构造方法的参数,和返回值"void"
//(3) 创建一个该类的对象
jobject r =env->NewObject(robotClass,robotConstruct,name,age,skillsHashMap);
//参数分别为:类名,构造方法ID,三个参数
3.在C++中创建一个Java的HashMap
// 1. 寻找hashmap类
jclass hashMap= env->FindClass("java/util/HashMap");
// 2. 寻找构造方法ID
jmethodID hashMap_init=env->GetMethodID(hashMap,"<init>", "()V");
// 3. 创建hashmap
jobject skillsHashMap=env->NewObject(hashMap,hashMap_init);
// 4. 寻找插入方法的ID
jmethodID hashMap_add =env->GetMethodID(hashMap,"put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
// 5. 按你的需求插入元素
using namespace std;
string skills[]={"移动","说话","唱歌","图像识别"};
int levels[]={5,4,4,2};
jclass classInteger=env->FindClass("java/lang/Integer");
jmethodID initInteger =env->GetMethodID(classInteger,"<init>", "(I)V");
for (int i = 0; i < sizeof(levels)/ sizeof(int); ++i) {
jstring s=env->NewStringUTF(skills[i].c_str());
jobject newInteger=env->NewObject(classInteger,initInteger,levels[i]);
env->CallObjectMethod(skillsHashMap,hashMap_add,s,newInteger);
}
4. 调用Java方法的参数签名 解析
(1)
你可能会看到,调用Java方法时最后一个参数奇奇怪怪,比如:
jmethodID hashMap_init=env->GetMethodID(hashMap,"<init>", "()V");
jmethodID hashMap_add =env->GetMethodID(hashMap,"put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
jmethodID initInteger =env->GetMethodID(classInteger,"<init>", "(I)V");
最后一个参数其实是调用该方法的签名,就是输入参数和返回值:
格式为:
"(输入参数类型1,类型2,类型3)返回值参数类型"
(2)
例如"(I)V"
表示输入参数为I,输出参数为V,这是一个宏定义,在jni.h
中定义的映射类型如下:
typedef union jvalue {
jboolean z;
jbyte b;
jchar c;
jshort s;
jint i;
jlong j;
jfloat f;
jdouble d;
jobject l;
} jvalue;
其中V表示void,所以"(I)V"
就是输入一个int返回void
(3)
对于非基本类型,要找到他们的类型位置。例如
"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"
表示输入两个参数,类型为Ljava/lang/Object
;
输出一个参数,类型为Ljava/lang/Object
(4)
如果没有输入参数,括号内就写空,但没有返回值,就要写成void,例如
"()V"
表示无输入参数,输出为void