Java通过jni调用C语言函数
使用的工具
- IntelliJ IDEA
- CLion
开始之前的注意事项
- 确保安装了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 484201132@qq.com
* @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
编译后的项目:
创建头文件
用cmd或者idea的终端执行命令,先切换到target目录下的classes目录下,然后执行命令:
javah -jni com.beiyoufamily.utils.IntegerUtils
后面这个是你包含native
方法的类的全类名。执行之后会得到一个com_beiyoufamily_utils_IntegerUtils.h
的c头文件。如图所示:
打开看了一下,头文件里面就是几个函数
创建c项目
导入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 <jni.h>
这一行在报错,修改为:#include "jni.h"
就可以了
实现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
在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
这个目录中: