JNI(java native interface),通过JNI的方式调用动态库步骤比较麻烦,不用额外引入依赖,对java项目工程依赖侵入为0,类中含有native
描述的方法都会与动态库去 一 一 映射,能通过System.load()
函数去加载动态库,这种方式主要使用的场景是java写好类(一般不是接口),让C或者C++去实现
通过jna的方式调用动态库的步骤就很简单了,但是不能使用java中的native
关键字,使用接口去管理所有的动态库方法,也不能通过System.load()
方法加载动态库,这种方式使用的主要场景是java去接入C或C++已经写好的函数方法
,为了快捷并且简单,还是推荐这种方式,这种方式之前已经介绍过了,本文主要介绍JNI的方式调用动态库。
步骤描述
-
编写java类(以下称为
A.java
)(这个类有包名与无包名操作是不一样的,全类名与动态库都是一一对应的,一定要注意这个地方,错了一点都加载不到最后的动态库) -
使用
javac
生成A.class
-
使用
javah
生成这个类的jni头文件(源码与字节码必须要同一个目录下),并且必须要在源码根目录下执行javah
命令,如果这个类有包名那么命令就是javah -classpath . org.A
,不带后缀,要同时检查A.java与A.class
文件同时存在 -
将生成的这个
org_A.h
,复制到Clion中开始写C++的实现代码 -
org_A.h
头文件中使用到了#include <jni.h>
头文件,这个头文件在jdk安装根目录下的include
目录中,那么就要将这个目录引入到Clion的CMakeLists.txt
中,具体为include_directories(D:/java/jdk/jdk11/include)
-
一般
org_A.h
会有大量的报红,不用管,一般操作没有失误的话编译都能通过 -
把动态库放到
D:\java\jdk\jdk8\jre\bin
目录下程序中就使用System.loadLibrary("libdlldemo");
加载 -
如果想把动态库放到任意目录下,程序中就使用
System.load("D:\\code\\test\\src\\main\\resources\\libdlldemo.dll");
加载
项目概览
1、编写NativeLibraryExample.java
package org;
public class NativeLibraryExample {
public static native void hello();
public static native int add(int a, int b);
public static void main(String[] args) {
System.load("D:\\code\\test\\myTestNett\\src\\main\\resources\\libdlldemo.dll");
// System.loadLibrary("libdlldemo");
hello();
System.out.println(add(1, 2));
}
}
2、cmd进入org目录下执行javac NativeLibraryExample.java
生成NativeLibraryExample.class
3、cmd进入源码根目录,也就是java
目录,执行javah -classpath . org.NativeLibraryExample
会生成jni头文件org_NativeLibraryExample.h
内容如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class org_NativeLibraryExample */
#ifndef _Included_org_NativeLibraryExample
#define _Included_org_NativeLibraryExample
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: org_NativeLibraryExample
* Method: hello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_org_NativeLibraryExample_hello(JNIEnv *, jclass);
/*
* Class: org_NativeLibraryExample
* Method: add
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_org_NativeLibraryExample_add(JNIEnv *, jclass, jint, jint);
#ifdef __cplusplus
}
#endif
#endif
4、将org_NativeLibraryExample.h
复制到Clion中并且相同的目录下编写org_NativeLibraryExample.cpp
文件,内容如下
#include "org_NativeLibraryExample.h"
#include <iostream>
JNIEXPORT void JNICALL Java_org_NativeLibraryExample_hello(JNIEnv * a, jclass b){
// 你的c++逻辑
std::cout << "这是有包名的动态库" << std::endl;
}
JNIEXPORT jint JNICALL Java_org_NativeLibraryExample_add(JNIEnv *, jclass, jint a, jint b){
// 你的c++逻辑
return a+b;
}
5、然后打开 CMD 使用MG64-posix中的g++编译org_NativeLibraryExample.cpp
文件
g++ -shared -o libdlldemo.dll -I"%JAVA_HOME%\include" -I"%JAVA_HOME%\include\win32" org_NativeLibraryExample.cpp
-shared:表示生成动态库
-o:指定输出文件名
-I:指定头文件搜索目录
6、将生成的libdlldemo.dll
复制到D:\java\jdk\jdk8\jre\bin
目录下,或者任意目录下
7、放在不同的目录下加载动态库的方式不同,把动态库放到D:\java\jdk\jdk8\jre\bin
目录下程序中就使用System.loadLibrary("libdlldemo");
加载。如果想把动态库放到任意目录下,程序中就使用System.load("D:\\code\\test\\src\\main\\resources\\libdlldemo.dll");
加载
8、将java工程中的org_NativeLibraryExample.h
与NativeLibraryExample.class
文件删除,启动NativeLibraryExample#main
测试
9、至此,jni生成dll步骤全部结束,可以编写更加复杂的c++代码了
标签:include,JAVA,java,System,C++,NativeLibraryExample,org,JNI,动态 From: https://www.cnblogs.com/hhddd-1024/p/17734626.html