首页 > 其他分享 >JNI 基础教学

JNI 基础教学

时间:2024-03-22 16:59:13浏览次数:27  
标签:Java String 基础 教学 env JNI JNIEnv native

/*常用引用数据类型对比
 * All object              jobject
 * java.lang.Class         jclass
 * java.lang.String        string
 * int[]                   jintArray
 * Object[]                jobjectArray
 *
 * JNI 函数签名信息
 * java支持函数重载,因此仅仅根据函数名是没法找到对应的JNI函数。
 * 为了解决这个问题,JNI将参数类型和返回值类型作为函数的签名信息
 *
 * JNI规范定义的函数签名信息格式: (参数1类型字符…)返回值类型字符
 *
 * 例子:Java函数 对应的 函数签名
 *  String sayHello2();           "()Ljava/lang/String;"
 *  long fun(int i,Class c)        "(ILjava/lang/Class;)J"
 *  void fun(byte[] bytes)         "([B)V"
 *
 *  JNI常用的数据类型及对应字符:
 *
 *  Java类型        对应字符
 *  void            V
 *  boolean         Z
 *  int             I
 *  long            J
 *  double          D
 *  float           F
 *  byte            B
 *  char            C
 *  short           S
 *  int[]           [i
 *  String          Ljava/lang/String;(后面一定要加;)
 *  Object[]        [Ljava/lang/object;
 *
 *
 *  JNIEnv 是个啥? 它是一个线程相关的结构体, 该结构体代表了 Java 在本线程的运行环境。通过JNIEnv可以调用到一系列JNI系统函数,
 *  用于访问Java成员变量何成员方法,调用Java构造方法创建Java对象等
 *
 *  JNIEnv线程相关性: 每个线程中都有一个 JNIEnv 指针。JNIEnv只在其所在线程有效, 它不能在线程之间进行传递
 *
 * */
MainActivity.java
public class MainActivity extends Activity {

    // Used to load the 'myapplication' library on application startup.
    static {
        System.loadLibrary("myapplication");
    }

    private ActivityMainBinding binding;

    private int code = 8;
    private String msg = "hello JNI";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        // Example of a call to a native method
        TextView tv = binding.sampleText;
        //java 调用 Native函数
        tv.setText(stringFromJNI());
        tv.setText(sayHello());
        tv.setText(sayHello2());
        tv.setText(sayAloveB(5,2)+"");

        testCallJava(MainActivity.this);
    }

    public void cCallJava(String str){
        Log.i("TAG","cCallJava:" +str);
        Toast.makeText(this,str,Toast.LENGTH_SHORT).show();
    }

    public native void testCallJava(MainActivity activity);

    /**
     * A native method that is implemented by the 'myapplication' native library,
     * which is packaged with this application.
     */
    public native String stringFromJNI();

    public native String sayHello();

    public native String sayHello2();

    public native int sayAloveB(int a,int b);
}
native-lib.cpp
#include <jni.h>
#include <string>
#include "android/log.h"

#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,"tww" ,__VA_ARGS__)


extern "C" JNIEXPORT jstring JNICALL
Java_com_autochips_myapplication_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_autochips_myapplication_MainActivity_sayAloveB(JNIEnv *env, jobject thiz, jint a, jint b) {
    // TODO: implement sayAloveB()
    jint ab = a + b;
    return ab;
}


//静态注册
extern "C"
JNIEXPORT jstring JNICALL
Java_com_autochips_myapplication_MainActivity_sayHello(
        JNIEnv *env, jobject /* this */) {
    std::string hello = "tang say Hello JNI";
    return env->NewStringUTF(hello.c_str());
}

//动态注册
jstring sayHello2(JNIEnv *env, jobject /* this */) {
    std::string hello = "tang sayHello2 ----------";
    //获得一维数组的类引用,即jintArray类型
    jclass intArrayClass = env->FindClass("[I");
    //构造一个指向jintArray类一维数组的对象数组,该对象数组初始大小为length,类型为 jsize
    jobjectArray jobjectArray1 = env->NewObjectArray(6, intArrayClass, NULL);
    return env->NewStringUTF(hello.c_str());
}

static const JNINativeMethod gMethods[] = {
        {"sayHello2",//对应java交互类的名字
         "()Ljava/lang/String;",//对应方法名的函数签名
         (jstring *) sayHello2}//对应 cpp交互类的指针函数
};

JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
    __android_log_print(ANDROID_LOG_INFO, "native", "Jni_OnLoad");
    JNIEnv *env = NULL;

    if (vm->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK)//从JavaVM获取JNIEnv,一般使用1.4的版本
        return -1;
    //注意:这里 FindClass 必须要和交互类的 包名对应上,并换成[/]符号
    jclass clazz = env->FindClass("com/autochips/myapplication/MainActivity");

    if (!clazz) {
        __android_log_print(ANDROID_LOG_INFO, "native", "cannot get class,"
                                                        "com/autochips/myapplication/MainActivity");
        return -1;
    }

    if (env->RegisterNatives(clazz, gMethods, sizeof(gMethods) / sizeof(gMethods[0]))) {
        __android_log_print(ANDROID_LOG_INFO, "native", "register native method failed!\n");
        return -1;
    }

    return JNI_VERSION_1_4;
}


//native函数调用Java函数
extern "C"
JNIEXPORT void JNICALL
Java_com_autochips_myapplication_MainActivity_testCallJava(JNIEnv *env, jobject thiz,
                                                           jobject activity) {
    // TODO: implement testCallJava()
    //获取MainActivity
    jclass cls = env->GetObjectClass(activity);
    //拿成员变量ID
    jfieldID codeId = env->GetFieldID(cls,"code","I");
    jfieldID msgId = env->GetFieldID(cls,"msg","Ljava/lang/String;");

    //通过id获取其值
    jint code = env->GetIntField(activity,codeId);
    jstring msg = (jstring)env->GetObjectField(activity,msgId);
    //获取java.lang.String对象中的内容
    const char *cMsg = env->GetStringUTFChars(msg,JNI_FALSE);//C++里面没有

    LOGI("code = %d,msg = %s",code,cMsg);
    env->ReleaseStringUTFChars(msg,cMsg);//用完String之后释放

    //找到函数ID
    jmethodID callJavaMethodId = env->GetMethodID(cls,"cCallJava","(Ljava/lang/String;)V");
    jstring  nativeMsg = env->NewStringUTF("java method cCallJava Go!!!");
    //调用java中的cCallJava函数
    env->CallVoidMethod(activity,callJavaMethodId,nativeMsg);

    // 这里的DeleteLocalRef可以不执行,在函数执行完毕后LocalRef会自动释放,
    // 但是在循环次数较多的循环中需要Delete,否则可能会溢出
    env->DeleteLocalRef(msg);
    env->DeleteLocalRef(nativeMsg);
    env->DeleteLocalRef(cls);
}

JNI 基础
native函数调用Java函数

标签:Java,String,基础,教学,env,JNI,JNIEnv,native
From: https://www.cnblogs.com/kato-T/p/18089835

相关文章

  • Aic 应用开发基础一(概念与场景)
    Agi通用人工智能应用概念与场景大家看到,自美国OpenAI主导的GPT发布以来,全球科技领域掀起了革命性的浪潮。比如最近看到的aigc人工绘图,智能机器人等行业,很多新概念掘起,随着人工智能技术的不断完善,ai能做的事越来越多,许多地方产业和企业在积极进行技术改革和产业支持。人工智能已......
  • 【Linux】基础 IO(动静态库)-- 详解
    一、前言为什么要使用别人的代码?主要是为了提高程序开发的效率和程序的健壮性。当别人把功能都实现了,然后我们再基于别人的代码去做二次开发,那么效率当然就提高了。其次,这里基于的别人当然不是随便找的一个人,而特指的是顶尖的工程师,也就是说如果我们的代码出了问题,一般不会......
  • 一、SpringBoot基础搭建
    本教程主要给初学SpringBoot的开发者,通过idea搭建单体服务提供手把手教学例程,主要目的在于理解环境的搭建,以及maven模块之间的整合与调用源码:jun/learn-springboot以商城项目为搭建例子,首先计划建1个父模块,3个子模块:父模块(你可以理解为共用模块,约定共用参数以及公用jar等)s......
  • 从零开始的terraform之旅 - 3命令部分- 部署基础架构 (plan apply destroy)
    3命令部分-部署基础架构(planapply)文章目录3命令部分-部署基础架构(planapply)部署基础架构planplanningmodes**Refresh-onlymode**仅刷新模式,非常有用PlanningOptions规划选项apply命令Plan**Options**apply选项destroy命令部署基础架构terraform的......
  • 时序分析:基础知识整理(一)
    好的时序是设计出来的,不是约束出来的。搬运自:孤独的单刀;大佬后面的是付费项目,所以涉及付费项目的我不会公开,本博客纯方便自己看做笔记。时钟抖动ClockJitter理想的时钟信号是完美的方波,但是实际的方波是存在一些时钟抖动的。那么什么是时钟抖动呢? 时钟抖动,ClockJitt......
  • 无计算机基础想进AI方向,可以通过以下几个阶段学习AI,具体建议如下:
    无计算机基础想进AI方向,可以通过以下几个阶段学习AI,具体建议如下:阶段一:数学与编程基础构建在这个阶段,学员将专注于夯实数学基础,涵盖统计学、线性代数和微积分等核心数学知识,确保对机器学习和深度学习算法背后的数学原理有深入理解。同时,系统学习Python语言,包括语法结构、数据类......
  • VPN基础
    一、VPN概念1、概述(1)虚拟专用网络(VPN)的功能是:在公用网络上建立专用网络,进行加密通讯。在企业网络中有广泛应用。VPN网关通过对数据包的加密和数据包目标地址的转换实现远程访问。VPN可通过服务器、硬件、软件等多种方式实现。(2)虚拟:不需要拥有实际的长途线路,使用公共的网络......
  • Three.js基础入门介绍——【毕业季】Three.js动态相册
    前言岁月匆匆,又是一年毕业季,这次做个动态相册展示图片,放些有意思的内容,一起回忆下校园生活吧。预期效果相册展示和点选切换,利用相机旋转和移动来实现一个点击切图平滑过渡的效果。实现流程基本流程1、搭建场景2、放置图片3、鼠标事件4、相机运动工程文件工程......
  • 禹晶、肖创柏、廖庆敏《数字图像处理(面向新工科的电工电子信息基础课程系列教材)》
    本书专为教材定制,历时15年的沉淀和积累,源自三位作者累加超百年科研和教学的积累。配套课件、教学大纲、实验指导书、MATLAB源代码、习题解答、微课、动图、拓展阅读等教辅资源,为教学提供全方位服务。若选用本书作为教材,则提供进一步的教学支撑。本书在Gonzalez所著的《数字......
  • 深度学习模型的基础--感知机
    AI大模型学习在当前技术环境下,AI大模型学习不仅要求研究者具备深厚的数学基础和编程能力,还需要对特定领域的业务场景有深入的了解。通过不断优化模型结构和算法,AI大模型学习能够不断提升模型的准确性和效率,为人类生活和工作带来更多便利。方向一:AI大模型学习的理论基础提示......