一. jni调用java中父类方法
在java中新建一个类,继承自Company:
scala
public class GoogleCompany extends Company {
public GoogleCompany() {
super();
Log.i("carey", "==== 调用了GoogleCompany构造.");
}
public GoogleCompany(String name) {
super(name);
}
@Override
public void salary() {
super.salary();
Log.i("carey", "==== Google公司发也工资了。");
}
}
并声明company对象和native方法:
java
private Company company = new GoogleCompany();
public native void callSuperMethod();
在cpp中实现方法:
ini
extern "C"
JNIEXPORT void JNICALL
Java_com_carey_myndk_MainActivity_callSuperMethod(JNIEnv *env, jobject thiz) {
jclass cls = env->GetObjectClass(thiz);
// 得到java中company属性id
jfieldID fid = env->GetFieldID(cls, "company", "Lcom/carey/myndk/Company;");
// 得到java中company属性
jobject company_obj = env->GetObjectField(thiz, fid);
// 得到company属性类
jclass company_cls = env->GetObjectClass(company_obj);
// 得到java中company属性对象的父类
jclass super_cls = env->GetSuperclass(company_cls);
// 得到父类方法
jmethodID salary_mid = env->GetMethodID(super_cls, "salary" , "()V");
// 调用方法
env->CallNonvirtualVoidMethod(company_obj, super_cls, salary_mid, NULL);
}
在java中调用callSuperMethod()方法后看日志打印:
打印了子类和父类无参构造函数中的日志,同时也打印了父类Company的salary()方法中的日志。
二. C对java传入的数组进行排序
我们将java数组传入到C中,C对数据进行升序排序,我们定义native方法:
java
public native void sortArray(int[] intArray);
实现该方法:
c
// 比较函数 comparator
int comparator(const void* a, const void* b) {
// 将 const void* 指针转换为 const int* 指针,再解引用得到 int 类型的值
int num1 = *(const int*)a;
int num2 = *(const int*)b;
if (num1 < num2) {
return -1;
} else if (num1 == num2) {
return 0;
} else {
return 1;
}
}
extern "C"
JNIEXPORT void JNICALL
Java_com_carey_myndk_MainActivity_sortArray(JNIEnv *env, jobject thiz, jintArray int_array) {
// 需要将java数组转成C中的数组
// 设立返回的是一个jint类型的指针,指向数组的头元素
jint *elems = env->GetIntArrayElements(int_array, NULL);
// 排序,java中有排序API,如Collections.sort
// 获取数组长度
int arr_len = env->GetArrayLength(int_array);
// 排序
qsort(elems, arr_len, sizeof(int), comparator);
// GetIntArrayElements是将数组拷贝了一份
// 这里需要更新java数组
// 参数1 原java数组
// 参数2 排序之后的数组
// 参数3是模式 (0代表java数组进行更新,并且释放C中数组;JNI_ABORT不更新java数组,但需要释放资源;JNI_COMMIT更新java数组,不释放C中数组)
env->ReleaseIntArrayElements(int_array, elems, 0);
}
java中调用该方法进行日志打印:
arduino
int[] intArray = new int[] {32, 12, 6, 5, 11, 9};
sortArray(intArray);
for (int i : intArray) {
Log.e("carey", "==== 排序后:" + i);
}
如果要更改为降序排序,只需要更改C中comparator()比较器规则即可:
arduino
// 比较函数 comparator
int comparator(const void* a, const void* b) {
// 将 const void* 指针转换为 const int* 指针,再解引用得到 int 类型的值
int num1 = *(const int*)a;
int num2 = *(const int*)b;
if (num1 > num2) { // 这里
return -1;
} else if (num1 == num2) {
return 0;
} else {
return 1;
}
}
三. C中创建数组,返回给java
在java中定义native方法,参数为返回数组的长度:
csharp
public native int[] getNativeArray(int len);
同时声明生成随机数的方法:
arduino
public int getRandomInt(int max) {
Random rd = new Random();
return rd.nextInt(max);
}
在C中实现该方法:
ini
extern "C"
JNIEXPORT jintArray JNICALL
Java_com_carey_myndk_MainActivity_getNativeArray(JNIEnv *env, jobject thiz, jint len) {
// 创建数组
jintArray jarr = env->NewIntArray(len);
// 转成C中数组
jint *elems = env->GetIntArrayElements(jarr, NULL);
// 获取java中的方法,生成随机数作为数组元素的值
jclass ndk_obj = env->GetObjectClass(thiz);
jmethodID mid = env->GetMethodID(ndk_obj, "getRandomInt", "(I)I");
// 赋值
for (int i = 0; i < len; ++i) {
jint result_int = env->CallIntMethod(thiz, mid, 100);
elems[i] = result_int;
}
// 同步
env->ReleaseIntArrayElements(jarr, elems, 0);
return jarr;
}
在java中调用该方法并打印日志:
ini
int[] nativeArray = getNativeArray(10);
for (int i : nativeArray) {
Log.e("carey", "==== 返回的数组元素:" + i);
}
四.总结:
今天主要是介绍了C中调用java类的父类方法和数组的相关操作。喜欢的点赞收藏,感谢!