使用MinGW gcc 创建DDL和调用DDL以及 Java 利用JNI 调用 dll

使用MinGW gcc 创建DDL和调用DDL

使用 gcc 编译生成 ddl 文件所会使用到的 gcc 命令

选项 解释
-Wall 生成所有警告信息
-o FILENAME 生成指定的输出文件,用在生成可执行文件时。
-shared 生成共享目标文件。通常用在建立共享库时。
-c 只激活预处理,编译,和汇编,也就是他只把程序做成obj文件,会生成 .0 文件
-S 只激活预处理和编译,就是指把文件编译成为汇编代码,会生成 .s 文件

创建动态链接库(.ddl文件)

隐式调用法


1.先创建一个测试文件夹

在这里插入图片描述

2.在测试文件夹中创建一个 <20171426.h>

/*
 * author : snowflake
 * date : 2019/09/04
 */
#ifndef _20171426_H_
#define _20171426_H_

#ifdef __cplusplus
extern "C" {
#endif

extern __declspec (dllexport) void sayHello();

#ifdef __cplusplus
}
#endif


#endif // ~_MY_DLL_H_

3.在测试文件夹中创建一个 <20171426.c>

#include <stdio.h>

void sayHello() {

    printf("%s", "小颖最可爱啦!!!");

}

4.创建一个测试文件 <test.c>

#include <stdio.h>
#include "20171426.h"

int main() {

    sayHello();
    return 0;
}

5.目录结构如下

在这里插入图片描述

按住 shift 键,右击鼠标会出现 在此处打Powershell 窗口

执行

gcc -Wall -shared 20171426.c -o 20171426.dll

或者

gcc --shared 20171426.c -o 20171426.dll

会生成一个 20171426.dll 文件

在这里插入图片描述

接着编译 test.c 文件

/*
 * gcc 是一个工具,小颖可以理解为 javac 进行编译
 * test.c 是测试源文件
 * 20171426.dll 是动态链接库文件,代表编译 test.c 文件时要用到 20171426.dll 链接库
 * -o 暂时不知道
 * test 生成的可执行文件名
 */
gcc test.c 20171426.dll -o test

会生成一个 test.exe 可执行文件

在这里插入图片描述

然后在控制台输入 .\test 即可执行

在这里插入图片描述

动态链接库

Java 调用动态链接库

  • 工具:IDEA
  • C语言编译工具:MinGW GCC
  • JDK 版本:1.8

创建 Java 工程

在这里插入图片描述

创建 JNI.java 文件

package xyz.snowflake.jni;

import org.junit.Test;

/**
 * @author snowflake
 * @create-date 2019-09-04 12:07
 */
public class JNI {

    public native void sayHello();

}

在这里插入图片描述

构建工程,为了生成 out 文件夹

在这里插入图片描述

使用如下命令

javac
-h
$ContentRoot$\jni
-d
$ContentRoot$\out\production\$ModuleName$
$FileDir$\$FileName$

执行后,会生成 <全类名(包名+类名)> + “.h” 头文件

本例中

javac
-h E:\Learning-records\大三上学期\计算机操作系统\dll\jni
-d E:\Learning-records\大三上学期\计算机操作系统\dll\out\production\dll
E:\Learning-records\大三上学期\计算机操作系统\dll\src\xyz\snowflake\jni\JNI.java

现在项目结构如下

在这里插入图片描述

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class xyz_snowflake_jni_JNI */

#ifndef _Included_xyz_snowflake_jni_JNI
#define _Included_xyz_snowflake_jni_JNI
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     xyz_snowflake_jni_JNI
 * Method:    sayHello
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_xyz_snowflake_jni_JNI_sayHello
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

然后实现头文件中定义的方法

JNI.c

#include <jni.h>
#include <stdio.h>
#include "xyz_snowflake_jni_JNI.h"

JNIEXPORT void JNICALL Java_xyz_snowflake_jni_JNI_sayHello(JNIEnv *env, jobject thisObj) {
   printf("%s", "Hello World!\n");
   return;
}

在这里插入图片描述

执行

gcc
-Wl,--kill-at
-I "$JDKPath$\include"
-I "$JDKPath$\include\win32"
-shared
$ContentRoot$\jni\$FileNameWithoutAllExtensions$.c
-o
$ContentRoot$\lib\$FileNameWithoutAllExtensions$.dll

本例中是

D:\MinGW\bin\gcc.exe
-Wl,--kill-at
-I "C:\Program Files\Java\jdk-10.0.2\include"
-I "C:\Program Files\Java\jdk-10.0.2\include\win32"
-shared E:\Learning-records\大三上学期\计算机操作系统\dll\jni\JNI.c
-o E:\Learning-records\大三上学期\计算机操作系统\dll\lib\JNI.dll

生成 JNI.dll 文件后的目录结构

在这里插入图片描述

然后创建测试类

package xyz.snowflake.jni;

/**
 * @author snowflake
 * @create-date 2019-09-05 21:15
 */
public class JNITest {

    static {
        System.loadLibrary("JNI");
    }

    public static void main(String[] args) {
        JNI jni = new JNI();
        jni.sayHello();
    }

}

此时项目结构如下

在这里插入图片描述

进行测试

会报如下错误

java.lang.UnsatisfiedLinkError: no JNI in java.library.path: [...]
	at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2654)
	at java.base/java.lang.Runtime.loadLibrary0(Runtime.java:876)
	at java.base/java.lang.System.loadLibrary(System.java:1875)
	at xyz.snowflake.jni.JNITest.<clinit>(JNITest.java:10)
Exception in thread "main"

解决方法

编辑配置,配置 VM

-Djava.library.path=<lib文件夹路径名,也就是 dll 文件所在的文件夹>

在这里插入图片描述

但是运行由会报如下的错误

java.lang.UnsatisfiedLinkError: E:\Learning-records\大三上学期\计算机操作系统\dll\lib\JNI.dll: Can't load IA 32-bit .dll on a AMD 64-bit platform
	at java.base/java.lang.ClassLoader$NativeLibrary.load0(Native Method)
	at java.base/java.lang.ClassLoader$NativeLibrary.load(ClassLoader.java:2424)
	at java.base/java.lang.ClassLoader$NativeLibrary.loadLibrary(ClassLoader.java:2481)
	at java.base/java.lang.ClassLoader.loadLibrary0(ClassLoader.java:2678)
	at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2643)
	at java.base/java.lang.Runtime.loadLibrary0(Runtime.java:876)
	at java.base/java.lang.System.loadLibrary(System.java:1875)
	at xyz.snowflake.jni.JNITest.<clinit>(JNITest.java:10)
Exception in thread "main"

解决方案,使用 X86 版本 的 JDK

我将 JDK 版本更换为 JDK1.8 X86 版本后,运行结果正常

在这里插入图片描述

结果如下

在这里插入图片描述

自己遇到的其他的错误


错误

����: �Ҳ������޷��������� semester
ԭ��: java.lang.ClassNotFoundException: semester

不知道什么原因

错误

����: �Ҳ������޷��������� semester

不知道什么原因

错误

Exception in thread "main" java.lang.UnsupportedClassVersionError: xyz/snowflake/jni/JNI has been compiled by a more recent version of the Java Runtime (class file version 54.0), this version of the Java Runtime only recognizes class file versions up to 52.0
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClass(Unknown Source)
	at java.security.SecureClassLoader.defineClass(Unknown Source)
	at java.net.URLClassLoader.defineClass(Unknown Source)
	at java.net.URLClassLoader.access$100(Unknown Source)
	at java.net.URLClassLoader$1.run(Unknown Source)
	at java.net.URLClassLoader$1.run(Unknown Source)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(Unknown Source)
	at java.lang.ClassLoader.loadClass(Unknown Source)
	at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
	at java.lang.ClassLoader.loadClass(Unknown Source)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Unknown Source)
	at com.intellij.junit4.JUnit4TestRunnerUtil.loadTestClass(JUnit4TestRunnerUtil.java:316)
	at com.intellij.junit4.JUnit4TestRunnerUtil.buildRequest(JUnit4TestRunnerUtil.java:147)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:46)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

解决方法

更换 JDK 版本一致

参考文章

https://www.cnblogs.com/lichmama/p/4126323.html
https://www.xuebuyuan.com/1528987.html

发布了80 篇原创文章 · 获赞 13 · 访问量 9247

猜你喜欢

转载自blog.csdn.net/qq_39424178/article/details/100573756