首页 > 编程语言 >JAVA代码使用JNI的方式调用C/C++动态库

JAVA代码使用JNI的方式调用C/C++动态库

时间:2023-09-27 23:24:28浏览次数:44  
标签:include JAVA java System C++ NativeLibraryExample org JNI 动态

  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");加载

项目概览

image

image

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.hNativeLibraryExample.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

相关文章

  • Java之包装类的算法小题的练习
     算法小题练习一:需求:键盘录入一些1~10日之间的整数,并添加到集合中。直到集合中所有数据和超过200为止。代码示例:publicclassTest1{publicstaticvoidmain(String[]args){/*键盘录入一些1~10日之间的整数,并添加到集合中。直到集合中所有数据和超......
  • 无涯教程-JavaScript - CHAR函数
    描述CHAR函数返回由数字指定的字符。使用CHAR将可能从其他类型的计算机上的文件中获得的代码页码转换为字符。语法CHAR(number)争论Argument描述Required/OptionalNumber1到255之间的数字,指定所需的字符。该字符来自Windows环境的ANSI字符集。RequiredNotes如......
  • Java for循环:编程新手的必备技能
    Java for循环和增强的for循环是一种控制流语句,它提供了一种紧凑的方法来迭代值范围。循环重复遍历代码,直到满足特定条件为止。在此期间,Java for循环具有不同类型。for循环增强for循环或foreachfor循环for循环是3个表达式的组合,需要理解才能有效地使用for循环。初始化表达式初......
  • JavaScript解密日记5
    引言:在从事JAVA工作的第五个年头,突然开始对js加密js解密感兴趣。开始了探索的路程1.JavaScript基础知识:JavaScript是一种用于Web开发的脚本语言,它包括以下基础概念:变量(Variables):用于存储数据的容器,可使用var、let或const关键字声明。数据类型(DataTypes):包括数字、字符串、布......
  • java的jdk配置环境变量
    安装JDK选择安装目录安装过程中会出现两次安装提示。第一次是安装jdk,第二次是安装jre。建议两个都安装在同一个java文件夹中的不同文件夹中。(不能都安装在java文件夹的根目录下,jdk和jre安装在同一文件夹会出错)如下图所示 1:安装jdk随意选择目录只需把默认......
  • java.net.ConnectException: Connection refused: no further information
    java.net.ConnectException:Connectionrefused:nofurtherinformation atsun.nio.ch.SocketChannelImpl.checkConnect(NativeMethod)~[na:1.8.0_91] atsun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:717)~[na:1.8.0_91] atio.netty.channe......
  • C++原子变量atomic详解
    b站视频文章1C++中原子变量确保共享变量的操作在执行时不会被其他线程的操作干扰。无法复制/移动对象。is_lock_free函数:atomic对象是否支持无锁操作(什么意思?如果atomic对象需要锁,那设为atomic对象的意义是什么?)std::atomic_flag是C++中的一个原子布尔类型,它用于实现原子锁......
  • 无涯教程-JavaScript - VARA函数
    描述VARA函数根据样本估算方差。除数字外,计算中还包括文本和逻辑值,如TRUE和FALSE。语法VARA(value1,[value2]...)争论Argument描述Required/Optionalvalue11to255valueargumentscorrespondingtoasampleofapopulation.RequiredValue2,...OptionalN......
  • 9.27日Java动手动脑练习
    1publicclassMain{2publicstaticvoidmain(String[]args){3Fooobj1=newFoo();4Fooobj2=newFoo();5System.out.println(obj1==obj2);6}7staticclassFoo{8Foo(){9}10int......
  • java数据类型拓展
    java数据拓展publicclassdemo3{publicstaticvoidmain(String[]args){//整数拓展:进制二进制0b十进制八进制0十六进制0xinti1=10;inti2=010;inti3=0x10;System.out.println(i1);Syste......