Java调用C++动态库超详细步骤讲解(附源码)

2025-04-08 15:50

本文主要是介绍Java调用C++动态库超详细步骤讲解(附源码),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《Java调用C++动态库超详细步骤讲解(附源码)》C语言因其高效和接近硬件的特性,时常会被用在性能要求较高或者需要直接操作硬件的场合,:本文主要介绍Java调用C++动态库的相关资料,文中通过代...

在某些项目中需要在Java工程中调用自定义的C++的动态库,分为以下两步,第一步:动态库生成;第二步:Java调用动态库。

一、直接调用C++库

第一步:动态库生成(vs2017+qt5.12.10)

1、新建工程时,一定要选择qt下的Qt Class Library 这个选项,如下图所示

Java调用C++动态库超详细步骤讲解(附源码)

2、工程创建成功后,可以在解决方案下看到有testLib.h、testLib.cpp和testlib_global.h三个基础的文件生成,如下图所示

Java调用C++动态库超详细步骤讲解(附源码)

3、下面我们简单写一个打印“vs2017+qt5.12.10生成动态库”的输出函数

testlib_global.h

#pragma once

#include <QtCore/qglobal.h>
#include <qDebug>

#include "jni.h"


#ifndef BUILD_STATIC
# if defined(TESTLIB_LIB)
#  define TESTLIB_EXPORT Q_DECL_EXPORT
# else
#  define编程 TESTLIB_EXPORT Q_DECL_IMPORT
# endif
#else
# define TESTLIB_EXPORT
#endif

testLib.h

#pragma once

#include "testlib_global.h"

class TESTLIB_EXPORT testLib
{
public:
    testLib();

	/**************************************************
	* @author 鬼魅-9527
	* @brief : 打印
	* @param-in: 无
	* @param-out : 无
	* @return : 是否成功
	* @date : 2025-01-01
	**************************************************/
	bool Java_SDK_PrintfString();
};

/*将接口转义供外部调用*/
extern "C"
{
	testLib obj;
	extern "C" _declspec(dllexport) bool __cdecl Java_SDK_PrintfString()
	{
		return obj.Java_SDK_PrintfString();
	}
}

testLib.cpp

#include "testLib.h"

testLib::testLib()
{
}

bool testLib::Java_SDK_PrintfString()
{
	/*使用QStringLiteral,否则中文输出会乱码*/
	qDebug() << QStringLiteral("vs2017+qt5.12.10生成动态库");

	return true;
}

注:java调用的c++动态库和python调用的动态库有不同的地方,在于接口的命名方式上,c++中接口命名必须以Java+JavaClassName+接口名,如:Java_SDK_PrintfString。

4、下面我们可以编译生成动态库

Java调用C++动态库超详细步骤讲解(附源码)

第二步:Java调用C++动态库

1、打开vs code 并在动态库目录下新建一个test.java文件

test.java

public class SDK {
    // 声明native方法
    public native boolean PrintfString();
    // 加载库
    static {
        System.loadLibrary("testLib"); // 对于Windows, 可能是"example.dll"; 对于linux, 可能是"libexample.so"
    } 
    public static void main(String[] args) {
        SDK ex = new SDK();
        boolean result = ex.PrintfString();
        System.out.println(result); 
    }
}

2、运行tets.java,如下所示

Java调用C++动态库超详细步骤讲解(附源码)

注:如果运行提示找不到动态库,将对应的动态库和对应依赖的库拷贝到Java执行目录bin下面。

二、调用带参数传递的C++库

在大多数情况下,我们使用动态库调用时,都涉及参数传递,以下是简单的参数传递列子。

注:在封装传参数的接口给Java使用时,需要使用到Java对C++提供的参数名,因此需要将java安装目录下的include文件夹拷贝到工程中,并在工程中添加jni.h文件(重之重‘~_~)

第一步:动态库封装

testlib_global.h

#pragma once

#include <QtCore/qglobal.h>
#include <qDebug>

#include "jni.h"


#ifndef BUILD_STATIC
# if defined(TESTLIB_LIB)
#  define TESTLIB_EXPORT Q_DECL_EXPORT
# else
#  define TESTLIB_EXPORT Q_DECL_IMPORT
# endif
#else
# define TESTLIB_EXPORT
#endif

testLib.h

#pragma once

#include "testlib_global.h"

class TESTLIB_EXPORT testLib
{
public:
    testLib();

	/**************************************************
	* @author 鬼魅-9527
	* @brief : 打印
	* @param-in: 无
	* @param-out : 无
	* @return : 是否成功
	* @date : 2025-01-01
	**************************************************/
	bool Java_SDK_PrintfString();
	/**************************************************
	* @author 鬼魅-9527
	* @brief : 参数传递
	* @param-in: num:数量,str;字符串
	* @return :字符串长度
	* @date : 2025-01-01
	**************************************************/
	jint Java_SDK_dataInputAndOutput(JNIEnv *env, jobject _obj, const jint num, const jstring str);
};

/*将接口转义供外部调用*/
extern "C"
{
	testLib obj;
	extern "C" _declspec(dllexport) bool __cdecl Java_SDK_PrintfString()
	{
		return obj.Java_SDK_PrintfString();
	}
	extern "C" _declspec(dllexport) jint __cdecl Java_SDK_dataInputAndOutput(JNIEnv *env, jobject _obj, const jint num, const jstring str)
	{
		return obj.Java_SDK_dataInputAndOutput(env, _obj, num, str);
	}
}

注:Java调用的c++传参的动态库,命名规则为:返回值 Java_类名_函数名(JNIEnv* env,jobject obj,参数1,参数2 ,等);

如:jint Java_SDK_ava_SDK_dataInputAndOutput(JNIEnv *env, jobject _obj, const jint num, const jstring str);
参数JNIEnv *env就是初始化虚拟机得到的JNI环境;

参数jobject _obj为该类的对象;

参数const jint num位参数1;

参数const jstring str为参数2。

其中(jint、jstring为jni.h文件中,对应Java中的int和string)

test.cpp

#include "testLib.h"

testLib::testLib()
{
}

bool testLib::Java_SDK_PrintfString()
{
	/*使用QStringLiteral,否则中文输出会乱码*/
	qDebug() << QStringLiteral("vs2017+qt5.12.10生成动态库");

	return true;
}

jint testLib::Java_SDK_dataInputAndOutput(JNIEnv *env, jobject _obj, const jint num, const jstring str)
{
    /*jstring转string*/
	std::string stdStr(env->GetStringUTFChars(str, NULL));
	env->ReleaseStringUTFChars(str, NULL);
	qDebug() << "input num:" << num << "input str:" << QString::fromStdString(stdStr);

	return num +stdStr.size();
}

4、编译生成动态库

Java调用C++动态库超详细步骤讲解(附源码)

第二步:Java调用C++动态库

1、打开vs code 并在动态库目录下新建一个test.java文件

test.java

public class SDK {
    // 声明native方法
    public native boolean PrintfString();
    public native int dataInputAndOutput(int num, String str);
 QQhnEvb   // 加载库
    static {
        System.loadLibrary("testLib"); // 对于Windows, 可能是"example.dll"; 对于Linux, 可能是"libexample.so"
China编程    } 
    public static void main(String[] args) {
        SDK ex = new SDK();
        boolean result = ex.China编程PrintfString();
        System.out.println(result); 
        int num = 10;
        String str = "Z:/Demo/testLib/x64/Release/testLib.dll";
        int len = ex.dataInputAndOutput(num,str);
        System.out.println(len); 
    }
}

2、运行tets.java,如下所示

Java调用C++动态库超详细步骤讲解(附源码)

注:如果运行提示找不到动态库,将对应的动态库和对应依赖的库拷贝到Java执行目录bin下面。

总结

到此这篇关于Java调用C++动态库的文章就介绍android到这了,更多相关Java调用C++动态库内容请搜索China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程China编程(www.chinasem.cn)!

这篇关于Java调用C++动态库超详细步骤讲解(附源码)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1154134

相关文章

java中pdf模版填充表单踩坑实战记录(itextPdf、openPdf、pdfbox)

《java中pdf模版填充表单踩坑实战记录(itextPdf、openPdf、pdfbox)》:本文主要介绍java中pdf模版填充表单踩坑的相关资料,OpenPDF、iText、PDFBox是三... 目录准备Pdf模版方法1:itextpdf7填充表单(1)加入依赖(2)代码(3)遇到的问题方法2:pd

Java Stream流之GroupBy的用法及应用场景

《JavaStream流之GroupBy的用法及应用场景》本教程将详细介绍如何在Java中使用Stream流的groupby方法,包括基本用法和一些常见的实际应用场景,感兴趣的朋友一起看看吧... 目录Java Stream流之GroupBy的用法1. 前言2. 基础概念什么是 GroupBy?Stream

C++11范围for初始化列表auto decltype详解

《C++11范围for初始化列表autodecltype详解》C++11引入auto类型推导、decltype类型推断、统一列表初始化、范围for循环及智能指针,提升代码简洁性、类型安全与资源管理效... 目录C++11新特性1. 自动类型推导auto1.1 基本语法2. decltype3. 列表初始化3

SpringBoot监控API请求耗时的6中解决解决方案

《SpringBoot监控API请求耗时的6中解决解决方案》本文介绍SpringBoot中记录API请求耗时的6种方案,包括手动埋点、AOP切面、拦截器、Filter、事件监听、Micrometer+... 目录1. 简介2.实战案例2.1 手动记录2.2 自定义AOP记录2.3 拦截器技术2.4 使用Fi

C++11右值引用与Lambda表达式的使用

《C++11右值引用与Lambda表达式的使用》C++11引入右值引用,实现移动语义提升性能,支持资源转移与完美转发;同时引入Lambda表达式,简化匿名函数定义,通过捕获列表和参数列表灵活处理变量... 目录C++11新特性右值引用和移动语义左值 / 右值常见的左值和右值移动语义移动构造函数移动复制运算符

最新Spring Security的基于内存用户认证方式

《最新SpringSecurity的基于内存用户认证方式》本文讲解SpringSecurity内存认证配置,适用于开发、测试等场景,通过代码创建用户及权限管理,支持密码加密,虽简单但不持久化,生产环... 目录1. 前言2. 因何选择内存认证?3. 基础配置实战❶ 创建Spring Security配置文件

Python对接支付宝支付之使用AliPay实现的详细操作指南

《Python对接支付宝支付之使用AliPay实现的详细操作指南》支付宝没有提供PythonSDK,但是强大的github就有提供python-alipay-sdk,封装里很多复杂操作,使用这个我们就... 目录一、引言二、准备工作2.1 支付宝开放平台入驻与应用创建2.2 密钥生成与配置2.3 安装ali

Spring Security 单点登录与自动登录机制的实现原理

《SpringSecurity单点登录与自动登录机制的实现原理》本文探讨SpringSecurity实现单点登录(SSO)与自动登录机制,涵盖JWT跨系统认证、RememberMe持久化Token... 目录一、核心概念解析1.1 单点登录(SSO)1.2 自动登录(Remember Me)二、代码分析三、

PyCharm中配置PyQt的实现步骤

《PyCharm中配置PyQt的实现步骤》PyCharm是JetBrains推出的一款强大的PythonIDE,结合PyQt可以进行pythion高效开发桌面GUI应用程序,本文就来介绍一下PyCha... 目录1. 安装China编程PyQt1.PyQt 核心组件2. 基础 PyQt 应用程序结构3. 使用 Q

springboot自定义注解RateLimiter限流注解技术文档详解

《springboot自定义注解RateLimiter限流注解技术文档详解》文章介绍了限流技术的概念、作用及实现方式,通过SpringAOP拦截方法、缓存存储计数器,结合注解、枚举、异常类等核心组件,... 目录什么是限流系统架构核心组件详解1. 限流注解 (@RateLimiter)2. 限流类型枚举 (