Android ndk-jni语法—— 4

一. 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类的父类方法和数组的相关操作。喜欢的点赞收藏,感谢!

相关推荐
2601_9672642815 分钟前
Jetpack Compose 实践指南:从入门到进阶
java·学习
m0_587383001 小时前
社区家政系统开发实战:从需求分析到上线部署全指南
java·spring boot·spring·需求分析
凤山老林1 小时前
动态 i18n 体系落地:Spring Boot 多租户热加载与前后端协同实践
java·spring boot·后端·i18n
东风破_1 小时前
TypeScript 高级类型进阶:keyof、Exclude、Record 与类型组合思想
前端·后端·typescript
白露与泡影1 小时前
解密 Pi 的 Harness 工程:Agent 会话如何实现持久化与恢复
java·人工智能·算法
DS随心转插件2 小时前
Grok生成的html怎么导出——AI导出鸭:大模型结构化输出的“最后一公里”工程化解构
前端·人工智能·ai·html·豆包·deepseek·ai导出鸭
又见情义2 小时前
RK3568 Android 13 驱动适配实战:从零开始让SDK在自己的板子上跑起来
android·arm开发·驱动开发
এ慕ོ冬℘゜2 小时前
使用 jQuery 动态渲染表格与状态切换
前端·javascript·jquery
Zane19942 小时前
HashMap 为什么要在长度16、容量必须是2的幂这些细节上较劲
java·后端
人间凡尔赛2 小时前
2026 前端必修:4 个让 CSS 脱胎换骨的现代新特性(附实战代码)
前端·css