Java通过jni调用C语言函数,IntelliJ IDEA,CLion,动态链接库dll,本地方法,native

Java通过JNI调用C语言函数的完整步骤
本文详细介绍了如何在Java项目中使用JNI(JavaNativeInterface)调用C语言函数。首先,确保安装并配置了mingw环境,然后在IntelliJIDEACLion中创建Java项目,定义本地方法。接着,通过`javah`命令生成C头文件,并创建C源文件实现这些方法。最后,编译C代码生成动态链接库,加载到Java程序中进行调用。

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这个目录中:
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值