JNI(Java Native Interface)
Java调用C/C++,C/C++调用Java的一套API
Eclipse + vs编写Jni流程:
1.编写native方法
2.javah命令,生成.h头文件
3.复制.h头文件到CPP工程中(Visual Studio中)
4.复制jni.h和jni_md.h文件到CPP工程中(从jdk中搜索复制,解决.h文件引用jni.h头文件报错)
5.实现.h头文件中声明的函数
6.生成dll动态库文件
7.配置dll文件所在目录到环境变量(也可不用配置,直接将.dll文件放到java工程根目录下)
8.重启Eclipse
C的函数名称:Java_完整类名_函数名
JNIEnv
在C中:
JNIEnv 结构体指针
env二级指针
在C++中:
JNIEnv 是一个结构体的别名
env 一级指针
1.为什么需要传入JNIEnv? 函数执行过程中需要JNIEnv
2.C++为什么没有传入? this
3.C++只是对C的那一套进行封装,给一个变量赋值为指针,这个变量是二级指针
具体操作流程:
1.在Eclipse中创建Java工程,在JniTest类中编写native方法:
package com.test.jni;
public class JniTest {
public native static String getStringFromC();
public static void main(String[] args) {
String text = getStringFromC();
System.out.println(text);
}
//加载动态库
static {
System.loadLibrary("jni_test");
}
}
2.打开cmd,进入工程目录下的src目录,执行javah + JniTest全包名
执行完成,会在src目录下生成.h头文件,如下图:
生成的.h头文件如下:
3.在Visual Studio中创建C工程
1)将.h头文件拷贝到c工程,并添加关联到项目(此时.h中#include<jni.h>头文件引入报错)
2)JDK中搜索jni.h,将jni.h和jni_md.h文件复制到C工程中,并修改引用为#include “jni.h”(解决jni.h头文件报错)
注:#include指令使用区别,系统头文件引入使用<>;第三方头文件引入使用" ",所以此处需修改引用为#include “jni.h”
3)创建c01.c文件,在c01.c中实现C函数
#include "com_test_jni_JniTest.h"
//函数实现
JNIEXPORT jstring JNICALL Java_com_test_jni_JniTest_getStringFromC
(JNIEnv *env, jclass jclass){
return (*env)->NewStringUTF(env, "C String");
}
4)资源配置
注:若操作系统为32位,可直接跳过,使用默认资源配置,若为64位,需修改平台为x64
5).dll动态库生成
->右键工程属性->如下:
配置类型修改为动态库(.dll)
–>右键工程–>生成(生成解决方案),即会在工程对应目录下生成.dll:
6)将vs中生成的.dll动态库拷贝到java工程的根目录下,运行java工程
运行java工程,输出结果如下:
Java调用C函数成功!
注:此处.dll文件须放到工程根目录下,System.loadLibrary(“jni_test”);系统动态加载时才能找到,否则会报路径错误;
若.dll文件有多个工程使用,可放到一个统一目录,在Path环境变量中配置存放路径,系统也能正确加载。