Java通过JNI技术调用C++动态链接库的helloword测试

JNI调用原理

原理就不细说了,其实就是写个库给Java调,可以百度一下Java JNI,下面是HelloWorld代码测试

编写一个本地测试类

java 复制代码
package com.my.study.cpp_jni;

/**
 * 测试Java调用C++库
 * <p>使用命令javac -h . NativeTest.java自动生成C头文件</p>
 * <p>到jdk中的include\win32下单jni.h和jni_md.h头文件拷过来</p>
 * <p>实现cpp文件</p>
 * <p>编译</p>
 * <p>导入</p>
 * <p>配置cpp库文件</p>
 * <p>System.load("D:/xxx/java/com/my/study/cpp_jni/MyLibrary.so");</p>
 *
 */
public class NativeTest {
    static {
        /*
        // 设置java.library.path路径
        System.setProperty("java.library.path", "/path/to/library");

        // 通过System.loadLibrary()加载库文件
        System.loadLibrary("mylibrary");
        */
        System.load("D:/xxx/java/com/my/study/cpp_jni/MyLibrary.dll");
    }

    private native void print();

    public static void main(String[] args) {
        new NativeTest().print();
    }
}

java文件格式说明

使用JavaC命令生成C语言的头文件.h文件

用命令javac -h . NativeTest.java自动生成C头文件

CMD 复制代码
javac -h . NativeTest.java

生成文件com_my_study_cpp_jni_NativeTest.h:

cpp 复制代码
/* DO NOT EDIT THIS FILE - it is machine generated */
#include "jni.h"
/* Header for class com_my_study_cpp_jni_NativeTest */

#ifndef _Included_com_my_study_cpp_jni_NativeTest
#define _Included_com_my_study_cpp_jni_NativeTest
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_my_study_cpp_jni_NativeTest
 * Method:    print
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_my_study_cpp_jni_NativeTest_print
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

com_my_study_cpp_jni_NativeTest.h文件格式说明

拷贝JDK include目录下的jni.h和win32/jni_md.h头文件到相同路径

修改com_my_study_cpp_jni_NativeTest.h文件的#include <jni.h>为#include "jni.h"引入方式,避免查找C/C++库

NativeTest.cpp实现C头文件函数

cpp 复制代码
#include<iostream>
#include "com_my_study_cpp_jni_NativeTest.h"


using namespace std;
JNIEXPORT void JNICALL Java_com_my_study_cpp_jni_NativeTest_print(JNIEnv *, jobject) {
  	cout << "Hello Word JNI" << endl;
  }

编译C++库文件

编译C源代码并创建本地库

// 编译C语言库

// gcc -ID:\xxx\Java\Java8\jdk\include\ -ID:\xxx\Java\Java8\jdk\include\win32\ NativeTest.c -shared -o MyLibrary.so

// 编译C++库

// g++ -ID:\xxx\Java\Java8\jdk\include\ -ID:\xxx\Java\Java8\jdk\include\win32\ NativeTest.cpp -shared -o MyLibrary.so

// gcc -I 表示将后面的目录表示为第n个头文件的目录

执行测试,报错

解决错误问题,确认gcc、g++版本是32还是64位

这里不如直接把vs装上测试,因为那个无法找到库文件的问题我弄了几个小时,这里不如直接装上vs,装好vs后几分钟就生成好dll库了

我这里使用VS2022生成动态链接库,装好创建一个C++项目

这里是刚才根据对应头文件和cpp实现文件创建的文件结构,文件都是上面的文件,把文件放到对应位置就行了

对了这里的pch.h预编译头去掉一下,因为用不到,要不然一直报错

使用vs生成动态链接库,把生成的代码放到D盘根目录,方便测试,修改一下Java测试代码,这里可以看到我这里使用g++指令生成的动态链接库比使用vs生成的动态链接库小,说明使用指令生成的动态链接库还差了什么东西在里面,我对C++也不熟悉,所以这里使用vs生成了

java 复制代码
/**
 * 测试Java调用C++库
 * <p>使用命令javac -h . NativeTest.java自动生成C头文件</p>
 * <p>到jdk中的include\win32下单jni.h和jni_md.h头文件拷过来</p>
 * <p>实现cpp文件</p>
 * <p>编译</p>
 * <p>导入</p>
 * <p>配置cpp库文件</p>
 * <p>System.load("D:/xxx/java/com/my/study/cpp_jni/_013_Cpp_VS_Dynamic_Link_Lib.dll");</p>
 * <p>System.loadLibrary("_013_Cpp_VS_Dynamic_Link_Lib");//不加dll</p>
 * Can't load IA 32-bit .dll on a AMD 64-bit platform:需要下载64位cpp编译器,不同cpu编译器不同
 */
public class NativeTest {
    static {
        System.load("D:/_013_Cpp_VS_Dynamic_Link_Lib.dll");
    }

    private native void print();

    public static void main(String[] args) {
        new NativeTest().print();
    }
}

idea运行测试:

这里可以看到运行了C++编译打印的字符串Hello World JNI,成功了,撒花

总结:

  1. 创建Java文件,函数用native标记
  2. 生成.h头文件
  3. 拷贝jni.h,jni_md.h文件,调整文件引用位置
  4. 实现头文件
  5. 生成动态链接库(这里使用VS)
  6. Java调用
相关推荐
BD_Marathon2 小时前
【Flink】部署模式
java·数据库·flink
鼠鼠我捏,要死了捏5 小时前
深入解析Java NIO多路复用原理与性能优化实践指南
java·性能优化·nio
CodeCraft Studio5 小时前
3D文档控件Aspose.3D实用教程:使用 C# 构建 OBJ 到 U3D 转换器
开发语言·3d·c#·3d渲染·aspose·3d文件格式转换·3d sdk
ningqw5 小时前
SpringBoot 常用跨域处理方案
java·后端·springboot
superlls5 小时前
(Redis)主从哨兵模式与集群模式
java·开发语言·redis
让我们一起加油好吗5 小时前
【基础算法】初识搜索:递归型枚举与回溯剪枝
c++·算法·剪枝·回溯·洛谷·搜索
郝学胜-神的一滴5 小时前
Horse3D游戏引擎研发笔记(七):在QtOpenGL环境下,使用改进的Uniform变量管理方式绘制多彩四边形
c++·3d·unity·游戏引擎·图形渲染·虚幻·unreal engine
chenglin0166 小时前
C#_gRPC
开发语言·c#
骑驴看星星a7 小时前
数学建模--Topsis(Python)
开发语言·python·学习·数学建模
叫我阿柒啊7 小时前
Java全栈工程师面试实战:从基础到微服务的深度解析
java·redis·微服务·node.js·vue3·全栈开发·电商平台