jni原理和实现

news2024/10/5 21:23:52

一、jni原理

主要就是通过数据类型签名和反射来实现java与c/c++方法进行交互的

数据类型签名对应表

javac/c++
booleanZ
byteB
charC
shortS
intI
longL
floatF
doubleD
voidV
objectL开头,然后以/分割包的完整类型,后面再加; 比如String的签名就是Ljava/long/String
Array以[开头,在加上数组元素类型的签名, 比如int[],签名是[I,int[][]的签名是[[I, object[]的签名是[Ljava/lang/Object

数据类型对应表

javac/c++
booleanjboolean
bytejbyte
charjchar
shortjshort
intjint
longjlong
floatjfloat
doublejdouble
voidvoid

引用类型对应表

javac/c++
stringjstring
objectjobject
classjclass
byte[]jbyteArray

二、实现jni

增加这三处

在这里插入图片描述

		ndk{
            // 设置支持的架构
            abiFilters 'armeabi-v7a', 'arm64-v8a'
        }
        externalNativeBuild {
	        cmake {
	            path file('src/main/cpp/CMakeLists.txt')
	            version '3.18.1'
	        }
    	}

CMakLists.txt

# 声明并命名项目。
cmake_minimum_required(VERSION 3.18.1)

# 声明并命名项目。
project("myc")

# 创建并命名一个库,设置其类型为静态或共享,并提供其源代码的相对路径。
# 您可以定义多个库,CMake会为您构建它们。
# Gradle会自动将共享库与您的APK一起打包。
add_library( # 设置库的名称。
        myc
        # 设置库为共享库。
        SHARED
        # 提供源文件的相对路径。
        native-lib.cpp )
        
# 在NDK中查找指定预构建的库,并将路径存储在变量中。
# 因为CMake默认将系统库添加到搜索路径中,所以您只需要指定公共NDK库的名称。
# CMake验证库是否存在,并在构建完成后完成其构建。
find_library( # 设置路径变量的名称。
        log-lib
        # 指定要CMake定位的NDK库名称。
        log )
        
# 指定目标库应链接的库。您可以链接多个库,例如在此构建脚本中定义的库、预构建的第三方库或系统库。
target_link_libraries( # 指定目标库。
        myc
        # 将目标库与log库(在NDK中)链接。
        \${log-lib} )

native-lib.cpp里面就可以写C/C++代码了

#include <jni.h>
#include <string>

/**
 * jni静态注册native方法
 */
//extern "C" {
//    JNIEXPORT jstring JNICALL Java_com_example_myc_MainActivity_stringFromJNI(JNIEnv *env, jobject /* this */) {
//        std::string hello = "Hello from C++";
//        return env->NewStringUTF(hello.c_str());
//    }
//
//    JNIEXPORT jint JNICALL Java_com_example_myc_MainActivity_intFromJNI(JNIEnv *env, jobject /* this */, jint a, jint b) {
//        return a + b;
//    }
//}
/**
 * jni动态注册native方法
 */
extern "C" {
    JNIEXPORT jstring JNICALL cpp_stringFromJNI(JNIEnv *env, jobject /* this */) {
        std::string hello = "Hello from C++";
        return env->NewStringUTF(hello.c_str());
    }

    JNIEXPORT jint JNICALL cpp_intFromJNI(JNIEnv *env, jobject obj/* this */, jint a, jint b) {
        /**
         * c++ 调用java方法
         */
        jobject m_object = env->NewGlobalRef(obj);//创建对象的本地变量
        jclass myClass = env->FindClass("com/example/myc/MainActivity");//找到类文件
        jmethodID myMethod = env->GetMethodID(myClass, "myMethod", "(Ljava/lang/String;)V");//在类文件下找到方法,第三个参数是方法的签名也就是方法的参数类型和返回类型
        env->CallVoidMethod(m_object, myMethod, env->NewStringUTF("c数据"));

        return a + b;
    }
}

//包名+类名字符串定义:
const char *class_name = "com/example/myc/MainActivity";
// 重点:函数表,相当于绑定,如果有多个方法要动态注册,在数组里面定义即可,第一个参数是java定义的函数名,第二个是函数签名,第三个是函数指针(也就是在c++自定义的函数名)
static const JNINativeMethod methods[] = {
        {"stringFromJNI", "()Ljava/lang/String;", (void *) cpp_stringFromJNI},
        {"intFromJNI",    "(II)I",                (void *) cpp_intFromJNI},
};
// 定义注册方法
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
//    LOGD("动态注册");
    JNIEnv *env;
    if ((vm)->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
//        LOGD("动态注册GetEnv  fail");
        return JNI_ERR;
    }

    // 获取类引用
    jclass clazz = env->FindClass(class_name);

    // 注册native方法,sizeof(methods) 表示 methods 数组占用的总字节数,sizeof(methods[0]) 表示 methods[0] 类型占用的字节数。将这两个值相除,得到 methods 数组中元素的数量。
    jint register_result = env->RegisterNatives(clazz, methods,
                                                sizeof(methods) / sizeof(methods[0]));
    if (register_result) { // 非零true 进if
//        LOGD("动态注册 fail regist_result = %d", regist_result);
    } else {
//        LOGI("动态注册 success result = %d", regist_result);
    }
    return JNI_VERSION_1_6;
}

void myMethod(JNIEnv *env, jobject obj) {
    jclass stringClass = env->FindClass("java/lang/String");
    jmethodID constructMethod = env->GetMethodID(stringClass, "<init>", "()V");
    jobject stringObj = env->NewObject(stringClass, constructMethod);

    std::string argStr = std::to_string(5);
    jstring result = (jstring) env->NewStringUTF(argStr.c_str());
    jobjectArray args = env->NewObjectArray(2, stringClass, stringObj);
    env->SetObjectArrayElement(args, 0, result);
    env->SetObjectArrayElement(args, 1, stringObj);
}

activity中

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding
    private var b = 0

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        
//        binding.sampleText.text = stringFromJNI()
        // java调用c++方法
        binding.sampleText.text = intFromJNI(1, b).toString()
        findViewById<Button>(R.id.btn_jia).setOnClickListener {
            binding.sampleText.text = intFromJNI(1, ++b).toString()
        }
    }

	/**
     * c++调用java方法
     */
    fun myMethod(str:String){
        Toast.makeText(this,"来自c端数据=$str",Toast.LENGTH_LONG).show()
    }

    /**
     * java调用c++方法
     */
    external fun stringFromJNI(): String
    external fun intFromJNI(a: Int, b: Int): Int

    companion object {
        // 导入c++库与CMakeLists中的库的命名一致
        init {
            System.loadLibrary("myc")
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1890077.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于jeecgboot-vue3的Flowable流程-集成仿钉钉流程(一)一些样式的调整使用

因为这个项目license问题无法开源&#xff0c;更多技术支持与服务请加入我的知识星球。 1、比如下面的发起人双击后出现的界面不正常&#xff0c; 看它的样式主要是这个里面的margin-left应该太小了&#xff0c; [data-v-45b533d5] .el-tabs__content { margin-top: 50px;mar…

实用麦克风话筒音频放大器电路设计和电路图

设计目标 输入电压最大值输出电压最大值电源Vcc电源Vee频率响应偏差20Hz频率响应偏差20kHz100dB SPL(2Pa)1.228Vrms5V0V–0.5dB–0.1dB 设计说明 此电路使用跨阻抗放大器配置中的运算放大器将驻极体炭精盒麦克风的输出电流转换为输出电压。此电路的共模电压是固定的&#xf…

第15届蓝桥杯Python青少组选拔赛(STEMA)2023年8月真题-附答案

第15届蓝桥杯Python青少组选拔赛&#xff08;STEMA&#xff09;2023年8月真题 题目总数&#xff1a; 11 总分数&#xff1a; 400 一、单选题 第 1 题 单选题 以下不符合 Python 语言变量命名规则的是&#xff08; &#xff09;。 A. k B. 2_k C. _k D. ok 答案 B …

cesium方案论证实现功能

仓库地址&#xff1a;Harvey-Andrew 演示地址&#xff1a;哔哩哔哩-满分观察网友z 文章目录 1. 场景加载2. 3D 模型2.1. 坐标转换2.2. 放置模型2.3. 调整模型2.4. 提交方案 3. 查看方案3.1. 场景还原3.2. 删除 1. 场景加载 加载Cesium的Melbourne Photogrammetry的倾斜摄影作…

【Threejs进阶教程-着色器篇】1. Shader入门(ShadertoyShader和ThreejsShader入门)

ThreejsShader入门 关于本Shader教程认识ShaderShader和Threejs的关系WebGLShaderThreejsShaderShadertoyShader其他Shader 再次劝退数学不好的人从ShaderToy开始Shader的代码是强类型glsl的类型&#xff0c;变量&#xff0c;内置函数&#xff0c;关键字关于uv基于UV的颜色处理…

Linux——高级IO

目录 IO 五种IO模型 阻塞式IO 非阻塞式IO 信号驱动IO 多路转接 异步IO 阻塞IO VS 非阻塞IO IO 网络的知识我们已经介绍完了&#xff0c;网络通信的本质就是IO&#xff0c;一方要发送数据&#xff0c;还要接收数据&#xff0c;这就是一次IO&#xff0c;所以我们原来说过…

解决VSCode中导入PyTorch时报错的HTTP错误与Channel冲突

问题描述与解释 在Anaconda中成功安装PyTorch&#xff0c;并进行了验证&#xff1a; (base) C:\Users\Hui>conda activate pytorch(pytorch) C:\Users\\Hui>python Python 3.8.19 (default, Mar 20 2024, 19:55:45) [MSC v.1916 64 bit (AMD64)] :: Anaconda, Inc. on …

安装windows服务,细节

1、选中服务代码&#xff0c;右键添加安装程序。 2、安装程序的权限一定改为local,否则安装时会提示null错误。 3、安装服务 InstallUtil D:\vs2022work\testFW\testFW\bin\Debug\testFW.exe p:InstallUtil 需要新建环境变量才能直接使用&#xff08;找到InstallUtil 工具所在…

沃尔核材:价值重估

当英伟达这个曾经的GPU行业龙头&#xff0c;伴随AI的发展成为AI芯片架构的供应商时&#xff0c;他就跳出了原本行业的竞争格局&#xff0c;曾经还能与之一战的超威半导体被远远甩在身后&#xff0c;成为宇宙第一公司。 这说的就是一家公司价值的重估。今天给大家聊的也是这样一…

【C++】相机标定源码笔记- RGB 相机与 ToF 深度传感器校准类

类的设计目标是为了实现 RGB 相机与 ToF 深度传感器之间的高精度校准&#xff0c;从而使两种类型的数据能够在同一个坐标框架内被整合使用。这在很多场景下都是非常有用的&#xff0c;比如在3D重建、增强现实、机器人导航等应用中&#xff0c;能够提供更丰富的场景信息。 -----…

学习笔记(linux高级编程)11

进程间通信 》信号通信 应用&#xff1a;异步通信。 中断&#xff0c;&#xff0c; 1~64&#xff1b;32应用编程。 如何响应&#xff1a; Term Default action is to terminate the process. Ign Default action is to ignore the signal. wait Core Default action is …

Eclipse运行main函数报 launch error

右键run as java application&#xff0c;运行main函数的时候报launch error 解决方式&#xff1a;文件右键run configurations 旧的是Project JRE&#xff0c;改成下图这个样子

视频去水印在线工具,视频去水印网站在线使用

在数字媒体时代&#xff0c;视频创作已成为越来越多人热衷的活动。然而&#xff0c;当我们想要对下载的视频进行二次创作或分享时&#xff0c;视频上的水印常常成为一个头疼的问题。本文将为您介绍几种免费且高效的去水印方法&#xff0c;让您在视频制作中游刃有余&#xff01;…

Studying-代码随想录训练营day28| 122.买卖股票的最佳时机II、55. 跳跃游戏、45.跳跃游戏II、1005.K次取反后最大化的数组和

第28天&#xff0c;贪心算法part02&#xff0c;题目难度在增加&#xff0c;要锻炼贪心思维能力(ง •_•)ง&#xff0c;编程语言&#xff1a;C 目录 122.买卖股票的最佳时机II 55. 跳跃游戏 45.跳跃游戏II 1005.K次取反后最大化的数组和 总结&#xff1a; 122.买卖股票的…

npm install puppeteer 报错 npm ERR! PUPPETEER_DOWNLOAD_HOST is deprecated解决办法

npm install puppeteer 报错如下&#xff1a; npm ERR! PUPPETEER_DOWNLOAD_HOST is deprecated. Use PUPPETEER_DOWNLOAD_BASE_URL instead. npm ERR! Error: ERROR: Failed to set up Chrome v126.0.6478.126! Set "PUPPETEER_SKIP_DOWNLOAD" env variable to sk…

绝区零国际服下载 一键下载绝区零国际服教程

绝区零是一款米哈游倾情打造的全新都市幻想动作角色扮演游戏。在游戏中&#xff0c;我们将扮演一名绳匠&#xff0c;这是为出于各种原因需要进入危险空洞的人提供指引的专业人士。您将与独特的角色一起踏上冒险之旅&#xff0c;携手探索空洞&#xff0c;对战强大敌人&#xff0…

每周题解:最大半连通子图

题目链接 最大半连通子图 题目描述 一个有向图 G ( V , E ) G\left(V,E\right) G(V,E) 称为半连通的 (Semi-Connected)&#xff0c;如果满足&#xff1a; ∀ u , v ∈ V \forall u,v\in V ∀u,v∈V&#xff0c;满足 u → v u\to v u→v 或 v → u v\to u v→u&#xff0…

番外篇 | 斯坦福提出即插即用二阶优化器Sophia :相比Adam实现2倍加速,显著节省大语言模型训练成本

前言:Hello大家好,我是小哥谈。大模型的预训练成本巨大,优化算法的改进可以加快模型的训练时间并减少训练开销。目前大模型的训练优化器基本上都采用Adam及其变体,并且Adam的应用已经有9个年头了,在模型优化方面相当于霸主的地位。但是能否够在优化器方面提高模型预训练效…

【每日刷题】Day79

【每日刷题】Day79 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. 1619. 删除某些元素后的数组均值 - 力扣&#xff08;LeetCode&#xff09; 2. 1365. 有多少小于当前…

python3.8安装详细教程

python3.8下载及安装详细教程 Python 3.8 是一个重要的Python版本&#xff0c;它引入了一系列新功能和改进。以下是对Python 3.8的详细概述&#xff0c;包括其关键特性、安装方法以及版本状态等信息。 Python 3.8的关键特性 海象运算符&#xff08;Walrus Operator&#xff09…