本次教程环境基于jdk19
(java环境),MinGW 8.1.0
(C语言环境,下载地址)
java要想成功调用dll文件,需要在dll制作的过程中由java生成头文件供C语言的程序调用并生成dll,否则会出现如下错误
Exception in thread "main" java.lang.UnsatisfiedLinkError: 'float[] com.jc.transfer.testClient.distributionCalculation(float[], int)'
该错误是因为java找不到dll中对应的方法。
现在通过一个简单的求和函数来介绍如何生成java可以调用的dll文件:
在java项目工程下创建dllDemo.java
,并写上求和接口Add
,需要用native
修饰。注意这里的包名。
package com.jc.transfer.utils;
public class dllDemo {
public native int Add(int a,int b);
}
随后通过命令行的方式进入当前文件所在目录,输入
javac dllDemo.java -h .
如图所示:
执行上述命令之后会在当前目录下生成两个文件dllDemo.class
和com_jc_transfer_utils_dllDemo.h
com_jc_transfer_utils_dllDemo.h
文件内容如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class com_jc_transfer_utils_dllDemo */
#ifndef _Included_com_jc_transfer_utils_dllDemo
#define _Included_com_jc_transfer_utils_dllDemo
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_jc_transfer_utils_dllDemo
* Method: Add
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_jc_transfer_utils_dllDemo_Add
(JNIEnv *, jobject, jint, jint);
#ifdef __cplusplus
}
#endif
#endif
这里可以发现生成的头文件对应的Add方法和java文件所在的包名相对应,这也是为什么调用不是自己生成的dll文件会出现异常的原因了,最后我们需要将#include
修改为#include "jni.h"
,后续需要导入jni.h文件。
在头文件同级目录下创建dllDemo.c
文件,内容如下,注意和头文件内Add函数的区别
#include "jni.h"
#include
#include "com_jc_transfer_utils_dllDemo.h"
JNIEXPORT jint JNICALL Java_com_jc_transfer_utils_dllDemo_Add
(JNIEnv *evn, jobject obj, jint a, jint b){
return a+b;
}
其中jni.h是jdk自带的文件,找到jdk安装目录下的include目录
将jni.h文件以及win32下的jni_md.h一同复制到dllDemo.c
所在目录
最后命令行进入当前目录,输入如下命令生成dllDemo.dll文件,其中${JAVA_HOME}为配置的java环境变量。
g++ -shared -o dllDemo.dll -I${JAVA_HOME}/include -I${JAVA_HOME}/include/java dllDemo.c
我们在dllDemo.java
文件中测试生成的dll。
package com.jc.transfer.utils;
public class dllDemo {
public native int Add(int a,int b);
static {
System.load("D:\\ideaWorkspace\\waterTransfer\\src\\main\\java\\com\\jc\\transfer\\utils\\dllDemo.dll");
}
public static void main(String[] args) {
dllDemo demo = new dllDemo();
System.out.println(demo.Add(2, 4));
}
}