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这个目录中:
 
 



















