JNI调用Java方法

Android  NDK  2023年6月29日 am8:08发布1年前 (2023)更新 91es.com站长
73 0 0

前言

前几天我们JNI的使用介绍过《JNI动态注册》和《JNI静态注册》,都是介绍Java的native方法,也就Java调用C或C++中的方法。

今天就介绍C或C++调用Java方法。记录于此,方便自己查阅。

正文

还是在之前基础上改,这里以《JNI动态注册》代码未基础,动态注册很方便和很简单。

功能介绍:模拟计算器加减法,通过native方法传入加或减类型和数值,通过类型判读,JNI中调用Java方法进行计算,再通过native方法返回结果。

Hello.java

package com.biumall.dynamic.one;
public class Hello {
    //1. load Hello.so
    static {
        System.loadLibrary("Hello");
    }
    // 2. define native computer()
    public static native int computer(String type, int a, int b);
    //add
    public int add(int x, int y) {
        return x + y;
    }
    //sub
    public int sub(int x, int y) {
        return x - y;
    }
}

Hello.c

这里依旧以C语言哈

#include <jni.h>
#include <android/log.h>
#include<stdio.h>
#include<string.h>

//LOG_TAG
#define LOG_TAG "from_dynamic_jni_+"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)

//获取数组大小
#define ARRAY_LENGTH(x) ((int)(sizeof(x) / sizeof((x)[0])))
//定义Hello.java类路径[包名+类名,只不过.换成了/]
//com.biumall.dynamic.one.Hello
#define DYNAMIC_CLASS "com/biumall/dynamic/one/Hello"

//声明方法
int c_add(JNIEnv *env, jclass jclazz, int x, int y);
int c_sub(JNIEnv *env, jclass jclazz, int x, int y);

//native 方法
JNIEXPORT jint JNICALL native_computer(JNIEnv *env, jclass jclazz, jstring type, jint a, jint b) {
    const char *charType = (*env)->GetStringUTFChars(env, type, 0);
    int count;
    if (!strcmp(charType, "-")) {
        count = c_sub(env, jclazz, a, b);
    } else if (!strcmp(charType, "+")) {
        count = c_add(env, jclazz, a, b);
    }
    return count;
}

//jni 调用 java add方法
int c_add(JNIEnv *env, jclass jclazz, int x, int y) {
    jmethodID methodID = (*env)->GetMethodID(env, jclazz, "add", "(II)I");
    jobject object = (*env)->AllocObject(env, jclazz);
    return (*env)->CallIntMethod(env, object, methodID, x, y);
}
//jni 调用 java sub方法
int c_sub(JNIEnv *env, jclass jclazz, int x, int y) {
    jmethodID methodID = (*env)->GetMethodID(env, jclazz, "sub", "(II)I");
    jobject object = (*env)->AllocObject(env, jclazz);
    return (*env)->CallIntMethod(env, object, methodID, x, y);
}

//定义Java和JNI函数的绑定表
// 方法数组,分别为:(方法名[java层定义的],方法签名,函数指针[c层对应替换的方法])
// 可以通过javac和javap 获取 方法签名
JNINativeMethod method_table[] = {
        {"computer", "(Ljava/lang/String;II)I", (void *) native_computer},
};

int registerNativeMethods(JNIEnv *env, const char *className, JNINativeMethod *methods,
                          int methods_size) {
    jclass clazz = NULL;
    //反射Java类
    clazz = (*env)->FindClass(env, className);
    if (NULL == clazz) {
        return JNI_ERR;
    }
    int result = (*env)->RegisterNatives(env, clazz, methods, methods_size);
    LOGD("registerNativeMethods result : %d", result);
    if (result < 0) {
        return JNI_ERR;
    }
    return JNI_OK;
}

JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved ){
    JNIEnv *env = NULL;
    int result = (*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_6);
    LOGD("JNI_OnLoad 1 result : %d", result);
    if(result != JNI_OK){
        return JNI_ERR;
    }
    result = registerNativeMethods(env, DYNAMIC_CLASS, method_table, ARRAY_LENGTH(method_table));
    LOGD("JNI_OnLoad 2 result : %d", result);
    if(result != JNI_OK){
        return JNI_ERR;
    }
    return JNI_VERSION_1_6;
}

动态注册变动的比较少。其实完全可以封装。

上面都有注释,这里就懒得解释了。

参考文章

  1. Android Studio NDK开发-JNI调用Java方法

 历史上的今天

  1. 2024: 刘明:从一幅寿桃走近一位画家(0条评论)
  2. 2021: Android应用被杀的日志分析记录(0条评论)
  3. 2020: [摘]List、Set、Map详解及区别(0条评论)
版权声明 1、 本站名称: 91易搜
2、 本站网址: 91es.com
3、 本站内容: 部分来源于网络,仅供学习和参考,若侵权请留言
3、 本站申明: 个人流水账日记,内容并不保证有效

暂无评论

暂无评论...

随机推荐

芒克:天空

太阳升起来天空血淋淋的犹如一块盾牌 日子像囚徒一样被放逐没有人来问我没有人宽恕我 我始终暴露着只是把耻辱用唾沫盖住 天空,天空把你的疾病从共和国的土地上扫除干净 可是,希望变成了泪水掉在地上我们怎么能确保明天的人们不悲伤...

Android监听Home键和Back键的简介

前言Home键和BACK是Android中最实用的,因此本文就简单的介绍一下监听HOME和BACK键。好记性不如烂笔头正文由于Android的管控越来越严格,HOME键已经无法拦截,但可以监听,BACK键的监听和拦截都可以。监听HOME键目前监听HOME的按键,可以监听:public...

王朔:上一秒痛苦,下一秒无聊

每天晚上我都睡得很晚,不是不困,而是不想睡,强迫自己不要睡。我似乎得了强迫症,我很忧郁。因为我总觉得一天什么都没干就这么过去了,实在不甘心!于是我就尽量延长这一天的时间。我真是个有志气的人,我很欣慰。志气是有了,可是找不到有志气的事情干,我很忧郁。幸好还有个电视,最妙的是还有个遥控器。遥控器真...

蒋勋:生活的美就在于从容不迫

我们童年的时候,父亲和母亲与我的关系很深,尤其是母亲。记得小时候回家,父亲问我你考第几名,我说第二名。父亲就严厉地问,为什么不是考第一名?当我正发抖时,我母亲会一把把我抱走,说,别理你爸爸。我好感谢那样的拥抱,彷佛把一切无法承担的压力都纾解了。我常感觉母亲有一双魔术师的手:我小时候盖的被子,是我母...

[摘]List、Set、Map详解及区别

一、List接口List是一个继承于Collection的接口,即List是集合中的一种。List是有序的队列,List中的每一个元素都有一个索引;第一个元素的索引值是0,往后的元素的索引值依次+1。和Set不同,List中允许有重复的元素。实现List接口的集合主要有:ArrayList、Li...

Ubuntu16.0.4安装搜狗输入法笔记

1、下载搜狗输入法安装包下载地址为:http://pinyin.sogou.com/linux/ ,如下图,要选择与自己系统位数一致的安装包。、2、使用命令安装搜狗输入法sudo dpkg -i sogoupinyin.deb3、设置搜狗输入为默认点击右上角的System setting...