• NDK学习笔记-JNI开发流程


    JNI(Java Native Interface)Java本地化接口,Java调用C/C++,C/C++调用Java的一套API接口

    实现步骤

    • 在Java源文件中编写native方法
    public native static String getStringFromC();
    
    • 到Java源代码src路径下,使用javah命令生成.h头文件
      注意:此处的参数为包名+类名
    //生成的头文件为:com_cj5785_jni_JniTest.h
    javah com.cj5785.jni.JniTest
    
    • 复制.h头文件到CPP工程中,修改文件包含
    //生成的C函数名:Java_完整类名_函数名
    #include "jni.h" //将#include <jni.h>修改
    
    • 复制jni.h和jni_md.h文件到CPP工程中
      jni.h和jni_md.h位于Java安装目录下

    • 实现.h头文件中声明的函数

    //为与头文件相匹配,此时将实现文件取名为:com_cj5785_jni_JniTest.c
    #include "com_cj5785_jni_JniTest.h"
    //函数实现
    JNIEXPORT jstring JNICALL Java_com_cj5785_jni_JniTest_getStringFromC
    (JNIEnv *env, jclass jcls)
    {
    	//将C的字符串转换为Java的字符串
    	return (*env)->NewStringUTF(env, "C String");
    }
    
    • 生成dll文件,供Java调用
      Debug -> 平台(x64) -> 确定
      项目(右键) -> 属性 -> 配置属性 -> 常规 -> 生成dll动态库

    • 将生成的dll文件放在Java的src目录同级下,加载动态库

    static{
        System.loadLibrary("");
    }
    

    整个java项目文件源代码

    package com.cj5785.jni;
    
    public class JniTest {
    	
    	static {
    		System.loadLibrary("JNITest");
    	}
    
    	public native static String getStringFromC();
    
    	public static void main(String[] args) {
    		
            String str = getStringFromC();
    		System.out.println(str);
    		
    	}
    }
    

    运行以后在控制台输出:C String
    在生成的dll过程中,会生成在相应配置的目录下

    JNI说明

    JNIEnv与env

    JNIEnv:结构体指针
    env:二级指针
    JNIEnv代表Java运行环境,调用Java中的代码

    • 在C中
      JNIEnv:结构体指针别名
      env:二级指针

    • 在C++中
      JNIEnv:一个结构体指针的别名
      env:一级指针

    • 为何需要传入JNIEnv?
      C函数执行过程中需要JNIEnv

    • C++为何没有传入?
      C++中有this指针,可以拿到当前指针,对C语言而言,要修改指针的值,只能通过二级指针

    • C++对C进行封装,给一个变量赋值为指针,这个变量就是二级指针

    struct JNINativeInterface_;
    struct JNIEnv_;
    #ifdef __cplusplus
    typedef JNIEnv_ JNIEnv;
    #else
    typedef const struct JNINativeInterface_ *JNIEnv;
    #endif
    

    jclass说明

    jclass代表native方法所属类的class对象,这里代表了JniTest.class

    C与C++的实现

    在函数实现的时候是不一样的
    c实现:

    #include "com_cj5785_jni_JniTest.h"
    JNIEXPORT jstring JNICALL Java_com_cj5785_jni_JniTest_getStringFromC
    (JNIEnv *env, jclass jcls)
    {
    	return (*env)->NewStringUTF(env, "C String");
    }
    

    C++实现

    JNIEXPORT jstring JNICALL Java_com_cj5785_jni_JniTest_getStringFromC
    (JNIEnv *env, jclass jcls)
    {
    	return env->NewStringUTF("C String");
    }
    

    JNIEnv实现模拟

    //JNIEnv结构体的指针别名
    typedef struct JNINativeInterface_* JNIEnv;
    //结构体
    struct JNINativeInterface_ {
    	char* (*NewStringUTF)(JNIEnv*, char*);
    };
    //函数实现
    char* NewStringUTF(JNIEnv* env, char* str){
    	//在NewStringUTF执行过程,仍然需要JNIEnv
    	return str;
    }
    void main(){
    	//实例化结构体
    	struct JNINativeInterface_ struct_env;
    	struct_env.NewStringUTF = NewStringUTF;
    	//结构体指针
    	JNIEnv e = &struct_env;
    	//结构体的二级指针
    	JNIEnv *env = &e;
    	//通过二级指针调用函数
    	char* str = (*env)->NewStringUTF(env,"abc");
    }
    
  • 相关阅读:
    java入门经验分享——记面向对象先导课程学习感想
    HashCode方法整理
    Java中vector用法整理
    Java中Iterator用法整理
    org.springframework.data.redis.RedisConnectionFailureException
    dubbo服务启动正常,但是访问不到服务,在监测中心也找不服务的原因之一
    【转】Elasticsearch Java Rest Client 指南
    【转】mybatis根据mapper执行sql的过程
    转:IDEA异常解决: org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)
    ES的常用查询与聚合
  • 原文地址:https://www.cnblogs.com/cj5785/p/10664682.html
Copyright © 2020-2023  润新知