Java通过jni调用C语言函数
使用的工具
IntelliJ IDEACLion
开始之前的注意事项
确保安装了mingw并配置了环境变量(下载地址:https://udomain.dl.sourceforge.net/project/mingw-w64/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/8.1.0/threads-win32/sjlj/x86_64-8.1.0-release-win32-sjlj-rt_v6-rev0.7z)
新建Java项目并创建本地方法
以int类型整数加减乘除为例: 代码:
package com.beiyoufamily.utils;
/**
* @author Yi Dai [email protected]
* @since 2023/6/10 11:22
*/
public class IntegerUtils {
/**
* 返回两数相加的和
*
* @param var1 第一个操作数
* @param var2 第二个操作数
* @return 两数之和
*/
public native int add(int var1, int var2);
/**
* 返回两数相减的差
*
* @param var1 第一个操作数
* @param var2 第二个操作数
* @return 两数之差
*/
public native int sub(int var1, int var2);
/**
* 返回两数相乘的积
*
* @param var1 第一个操作数
* @param var2 第二个操作数
* @return 两数之积
*/
public native int mul(int var1, int var2);
/**
* 返回两数相除的商
*
* @param var1 第一个操作数
* @param var2 第二个操作数
* @return 两数之商
*/
public native int div(int var1, int var2);
}
关键字native表示要调用一个本地方法,通常来说也就是调用c或者c++的结构。
编译Java项目
Build - build project 编译后的项目: ![在这里插入图片描述](https://img-blog.csdnimg.cn/752d50d3094b49438000a52ddbe0bedf.png)
创建头文件
用cmd或者idea的终端执行命令,先切换到target目录下的classes目录下,然后执行命令: javah -jni com.beiyoufamily.utils.IntegerUtils 后面这个是你包含native方法的类的全类名。执行之后会得到一个com_beiyoufamily_utils_IntegerUtils.h的c头文件。如图所示: 打开看了一下,头文件里面就是几个函数 ![在这里插入图片描述](https://img-blog.csdnimg.cn/3c3f18fa220c42c7bf00ffaadce89943.png)
创建c项目
![在这里插入图片描述](https://img-blog.csdnimg.cn/9c68fc69cdc1444bada6dd8ea8a3a7e8.png)
导入c头文件
首先将刚才javah生成的com_beiyoufamily_utils_IntegerUtils.h头文件拷贝到c项目的根目录中 然后将%JAVA_HOME%\include\jni.h和%JAVA_HOME%\include\win32\jni_md.h两个文件拷贝到c项目的根目录,这两个文件在哪儿取决于你JAVA_HOME环境变量配置到什么地方的。如图所示的三个文件就是刚才操作的结果: 上一步操作完了之后可以发现com_beiyoufamily_utils_IntegerUtils.h头文件中#include 这一行在报错,修改为:#include "jni.h"就可以了 ![在这里插入图片描述](https://img-blog.csdnimg.cn/6fe3acc067b246a5b816b92482318f23.png)
实现C函数
新建一个c源文件,我就起名叫integer_utils.c了,名字可以随意 导入javah生成的那个头文件,并实现头文件里面的方法: 代码:
//
// Created by 48420 on 2023/6/12.
//
#include "com_beiyoufamily_utils_IntegerUtils.h"
JNIEXPORT jint JNICALL Java_com_beiyoufamily_utils_IntegerUtils_add
(JNIEnv *env, jobject obj, jint var1, jint var2) {
return var1 + var2;
}
JNIEXPORT jint JNICALL Java_com_beiyoufamily_utils_IntegerUtils_sub
(JNIEnv *env, jobject obj, jint var1, jint var2) {
return var1 - var2;
}
JNIEXPORT jint JNICALL Java_com_beiyoufamily_utils_IntegerUtils_mul
(JNIEnv *env, jobject obj, jint var1, jint var2) {
return var1 * var2;
}
JNIEXPORT jint JNICALL Java_com_beiyoufamily_utils_IntegerUtils_div
(JNIEnv *env, jobject obj, jint var1, jint var2) {
return var1 / var2;
}
生成动态链接库
点击CLion的Build - Build project。如果报错,可以尝试先点击一下File - Reload CMake project,然后再次尝试构建 构建完成之后即可看到项目目录下的cmake-build-debug目录下已经有了一个名为:libjni_test.dll的动态链接库。这个库可以改名的,叫什么无所谓,比如我等下把它改名为abc.dll ![在这里插入图片描述](https://img-blog.csdnimg.cn/6c7ca7456fca492289e26a7ad23d9239.png)
在java中加载动态链接库,调用本地方法
调用System.load方法加载刚刚得到的libjni_test.dll动态链接库,System.load的参数是动态链接库的绝对路径
然后调用本地方法: 当然也可以使用System.loadLibrary方法来加载动态链接库,不过你需要把你的动态链接库拷贝到系统属性java.library.path指定的一个任意目录中,并且不能带扩展名,可以用System.getProperty传入java.library.path获得java.library.path的目录,如图: 只需要将动态链接库拷贝到这里面的任何一个目录(前提是其他目录中没有重名的动态链接库)即可,比如我放到C:\Program Files\Common Files\Oracle\Java\javapath这个目录中: ![在这里插入图片描述](https://img-blog.csdnimg.cn/850f86ad23a7478a957bf6b67f0b4586.png)
|