【JNI调用DLL动态库】Java使用JNI调用DLL动态链接库学习记录

前言

本篇文章主要记录如何使用JNI一步步完成Java调用C/C++类库,仅作学习记录,案例很简单,步骤也很明确,会通过详细截图的形式来进行演示。

JNI也就是Java Native Interface的简称,中文是“Java本地调用”。通常在Java程序中的函数可以调用Native语言写的函数,Native一般指的是C/C++编写的函数。使用JNI的目的就是为了屏蔽不同操作系统平台的差异性,通过Java语言来调用Native语言的功能模块。

但是总体来说,使用JNI开发很复杂,所以有大神就进行了封装,使用JNA,有兴趣的可以去学习一下。

示例

STEP - 1 : 新建Java工程,在Java类中声明native的方法
这里写图片描述

STEP - 2 : 在新建的项目中创建package,并且在包下创建一个Class(类)。
这里写图片描述

接下来,在该类中添加如下代码:

public class JavaInvokeCPlus {

    // 声明为native,表明是有外部来实现的
    public native String returnHelloWorldToUpcase(String string);
    public native void sayHelloWolrd();

}

STEP - 3 : 使用Javah命令生成native方法的声明的C/C++头文件
1️⃣ 编译Java文件
打开文件位置:右键Java文件 – Properties – Location – Show In System Explorer
这里写图片描述

按住shift键,同时在文件夹内空白处右击,选择“在此处打开命令窗口”,进入命令行【也可以使用其他方式进入到该目录下】。
这里写图片描述

编译:

javac .\JavaInvokeCPlus.java

这里写图片描述
会在当前目录下生成一个.class文件

注意:如果报错-错误:编码GBK的不可映射字符,解决办法:javac encoding UTD-8 ./JavaInvokeCPlus.java

2️⃣ 使用javah命令生成.h头文件

javah -d E:\workspace\JavaInvokeCPlus\bin\cn\com\esu
nny\jnitest -jni cn.com.esunny.jnitest.JavaInvokeCPlus

这里写图片描述

其中,javah中各个命令的意思是:

-classpath <路径> 用于装入类的路径
-d <目录> 输出目录
-jni 生成 JNI样式的头文件(默认)

注意事项:
*1:我们的命令符的执行位置是源代码目录E:\workspace\JavaInvokeCPlus\src,否则会报错:未找到cn.com.esunny.jnitest.JavaInvokeCPlus 的类文件
Maven工程是在src/main/java目录下操作

*2:-jni 后面的路径是包名+类名
*3:-jni 后面跟的文件的末尾不加上class后缀

3️⃣ 打开输出目录,然后我们可以看到在bin目录下多了一个.h头文件。
打开我们可以看到如下代码:
这里写图片描述

STEP - 4 : 使用VS2013生成DLL动态链接库文件
1️⃣ 新建项目
文件–新建–项目–Visual C++模块–Win32–Win32控制台应用程序–输入项目名称
这里写图片描述

应用程序选择DLL, 附加选项选择空项目 – 完成
这里写图片描述

2️⃣ 引入头文件

一个是刚刚使用javah生成的头文件
jni.h
jni_md.h

jni.h和jni_md.h这两个头文件需要在JDK中拷贝,博主这里使用的是JDK7的,现在将这三个头文件拷贝到C++工程的目录下。jdk的头文件在jdk的安装目录下,这两个文件的目录如下:

jni.h               --  %JAVA_HOME%\include
jni_md.h            --  %JAVA_HOME%\include\win32

VS2013项目工程目录结构如下:
这里写图片描述

然后将这三个头文件导入vs2013中:
这里写图片描述

修改编译产生的头文件的错误信息,将引入头文件的<>修改为”“:
这里写图片描述

3️⃣ 实现接口方法
源文件工程目录下新建一个cpp文件,引入编译产生的头文件

#include<iostream>
#include "cn_com_esunny_jnitest_JavaInvokeCPlus.h"
#include <string>
#include <cctype>
#include <algorithm>
using namespace std;

/*
* Class:     com_cjzheng_service_JavaInvodeCPlus
* Method:    returnHelloWorldToUpcase
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_cjzheng_service_JavaInvodeCPlus_returnHelloWorldToUpcase
(JNIEnv *, jobject, jstring str) {
    return str;
}

/*
* Class:     com_cjzheng_service_JavaInvodeCPlus
* Method:    sayHelloWolrd
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_cjzheng_service_JavaInvodeCPlus_sayHelloWolrd
(JNIEnv *, jobject) {
    cout << "Hello World" << endl;
}

4️⃣ 选择编译平台
项目–属性–配置管理器–活动解决方案平台–新建–新建解决方案平台
这里写图片描述

5️⃣ 编译动态库
右键项目 – 生成 – 控制台提示“========== 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========”
这里写图片描述

未完,待续

猜你喜欢

转载自blog.csdn.net/changqing5818/article/details/78259570