Java調(diào)用C++動(dòng)態(tài)庫(kù)超詳細(xì)步驟講解(附源碼)
在某些項(xiàng)目中需要在Java工程中調(diào)用自定義的C++的動(dòng)態(tài)庫(kù),分為以下兩步,第一步:動(dòng)態(tài)庫(kù)生成;第二步:Java調(diào)用動(dòng)態(tài)庫(kù)。
一、直接調(diào)用C++庫(kù)
第一步:動(dòng)態(tài)庫(kù)生成(vs2017+qt5.12.10)
1、新建工程時(shí),一定要選擇qt下的Qt Class Library 這個(gè)選項(xiàng),如下圖所示

2、工程創(chuàng)建成功后,可以在解決方案下看到有testLib.h、testLib.cpp和testlib_global.h三個(gè)基礎(chǔ)的文件生成,如下圖所示

3、下面我們簡(jiǎn)單寫(xiě)一個(gè)打印“vs2017+qt5.12.10生成動(dòng)態(tài)庫(kù)”的輸出函數(shù)
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: 無(wú)
* @param-out : 無(wú)
* @return : 是否成功
* @date : 2025-01-01
**************************************************/
bool Java_SDK_PrintfString();
};
/*將接口轉(zhuǎn)義供外部調(diào)用*/
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,否則中文輸出會(huì)亂碼*/
qDebug() << QStringLiteral("vs2017+qt5.12.10生成動(dòng)態(tài)庫(kù)");
return true;
}
注:java調(diào)用的c++動(dòng)態(tài)庫(kù)和Python調(diào)用的動(dòng)態(tài)庫(kù)有不同的地方,在于接口的命名方式上,c++中接口命名必須以Java+JavaClassName+接口名,如:Java_SDK_PrintfString。
4、下面我們可以編譯生成動(dòng)態(tài)庫(kù)

第二步:Java調(diào)用C++動(dòng)態(tài)庫(kù)
1、打開(kāi)vs code 并在動(dòng)態(tài)庫(kù)目錄下新建一個(gè)test.java文件
test.java
public class SDK {
// 聲明native方法
public native boolean PrintfString();
// 加載庫(kù)
static {
System.loadLibrary("testLib"); // 對(duì)于Windows, 可能是"example.dll"; 對(duì)于Linux, 可能是"libexample.so"
}
public static void main(String[] args) {
SDK ex = new SDK();
boolean result = ex.PrintfString();
System.out.println(result);
}
}
2、運(yùn)行tets.java,如下所示

注:如果運(yùn)行提示找不到動(dòng)態(tài)庫(kù),將對(duì)應(yīng)的動(dòng)態(tài)庫(kù)和對(duì)應(yīng)依賴的庫(kù)拷貝到Java執(zhí)行目錄bin下面。
二、調(diào)用帶參數(shù)傳遞的C++庫(kù)
在大多數(shù)情況下,我們使用動(dòng)態(tài)庫(kù)調(diào)用時(shí),都涉及參數(shù)傳遞,以下是簡(jiǎn)單的參數(shù)傳遞列子。
注:在封裝傳參數(shù)的接口給Java使用時(shí),需要使用到Java對(duì)C++提供的參數(shù)名,因此需要將java安裝目錄下的include文件夾拷貝到工程中,并在工程中添加jni.h文件(重之重‘~_~)
第一步:動(dòng)態(tài)庫(kù)封裝
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: 無(wú)
* @param-out : 無(wú)
* @return : 是否成功
* @date : 2025-01-01
**************************************************/
bool Java_SDK_PrintfString();
/**************************************************
* @author 鬼魅-9527
* @brief : 參數(shù)傳遞
* @param-in: num:數(shù)量,str;字符串
* @return :字符串長(zhǎng)度
* @date : 2025-01-01
**************************************************/
jint Java_SDK_dataInputAndOutput(JNIEnv *env, jobject _obj, const jint num, const jstring str);
};
/*將接口轉(zhuǎn)義供外部調(diào)用*/
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調(diào)用的c++傳參的動(dòng)態(tài)庫(kù),命名規(guī)則為:返回值 Java_類名_函數(shù)名(JNIEnv* env,jobject obj,參數(shù)1,參數(shù)2 ,等);
如:jint Java_SDK_ava_SDK_dataInputAndOutput(JNIEnv *env, jobject _obj, const jint num, const jstring str);
參數(shù)JNIEnv *env就是初始化虛擬機(jī)得到的JNI環(huán)境;
參數(shù)jobject _obj為該類的對(duì)象;
參數(shù)const jint num位參數(shù)1;
參數(shù)const jstring str為參數(shù)2。
其中(jint、jstring為jni.h文件中,對(duì)應(yīng)Java中的int和string)
test.cpp
#include "testLib.h"
testLib::testLib()
{
}
bool testLib::Java_SDK_PrintfString()
{
/*使用QStringLiteral,否則中文輸出會(huì)亂碼*/
qDebug() << QStringLiteral("vs2017+qt5.12.10生成動(dòng)態(tài)庫(kù)");
return true;
}
jint testLib::Java_SDK_dataInputAndOutput(JNIEnv *env, jobject _obj, const jint num, const jstring str)
{
/*jstring轉(zhuǎn)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、編譯生成動(dòng)態(tài)庫(kù)

第二步:Java調(diào)用C++動(dòng)態(tài)庫(kù)
1、打開(kāi)vs code 并在動(dòng)態(tài)庫(kù)目錄下新建一個(gè)test.java文件
test.java
public class SDK {
// 聲明native方法
public native boolean PrintfString();
public native int dataInputAndOutput(int num, String str);
// 加載庫(kù)
static {
System.loadLibrary("testLib"); // 對(duì)于Windows, 可能是"example.dll"; 對(duì)于Linux, 可能是"libexample.so"
}
public static void main(String[] args) {
SDK ex = new SDK();
boolean result = ex.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、運(yùn)行tets.java,如下所示

注:如果運(yùn)行提示找不到動(dòng)態(tài)庫(kù),將對(duì)應(yīng)的動(dòng)態(tài)庫(kù)和對(duì)應(yīng)依賴的庫(kù)拷貝到Java執(zhí)行目錄bin下面。
總結(jié)
到此這篇關(guān)于Java調(diào)用C++動(dòng)態(tài)庫(kù)的文章就介紹到這了,更多相關(guān)Java調(diào)用C++動(dòng)態(tài)庫(kù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java學(xué)生信息管理系統(tǒng)設(shè)計(jì)(數(shù)據(jù)庫(kù)版)
這篇文章主要為大家詳細(xì)介紹了數(shù)據(jù)庫(kù)版的Java學(xué)生信息管理系統(tǒng)設(shè)計(jì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-11-11
深入解析Java的設(shè)計(jì)模式編程中的模板方法模式
這篇文章主要介紹了深入解析Java的設(shè)計(jì)模式編程中的模板方法模式, 模版方法模式由一個(gè)抽象類和一個(gè)(或一組)實(shí)現(xiàn)類通過(guò)繼承結(jié)構(gòu)組成,需要的朋友可以參考下2016-02-02
簡(jiǎn)單實(shí)現(xiàn)java數(shù)獨(dú)游戲
這篇文章主要教大家如何簡(jiǎn)單實(shí)現(xiàn)java數(shù)獨(dú)游戲,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12
SpringData JPA基本/高級(jí)/多數(shù)據(jù)源的使用詳解
這篇文章主要介紹了SpringData JPA基本/高級(jí)/多數(shù)據(jù)源的使用詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02
MyBatis框架搭建時(shí)依賴包引入異常的問(wèn)題解決
在使用IDEA環(huán)境搭建MyBatis框架時(shí),可能會(huì)因?yàn)橐蕾嚢姹具^(guò)低導(dǎo)致兼容性問(wèn)題,本文就來(lái)介紹一下MyBatis框架搭建時(shí)依賴包引入異常的問(wèn)題解決,感興趣的可以來(lái)了解一下2024-10-10
JavaWeb通過(guò)IDEA配置Servlet操作流程詳解
這篇文章主要介紹了JavaWeb通過(guò)IDEA配置Servlet實(shí)現(xiàn)流程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2022-10-10
Java實(shí)現(xiàn)公用實(shí)體類轉(zhuǎn)Tree結(jié)構(gòu)
這篇文章主要為大家介紹了一個(gè)Java工具類,可以實(shí)現(xiàn)Java公用實(shí)體類轉(zhuǎn)Tree結(jié)構(gòu),文中的示例代碼簡(jiǎn)潔易懂,感興趣的小伙伴可以參考一下2024-10-10
聊聊SpringBoot整合Nacos自動(dòng)刷新配置的問(wèn)題
Nacos作為SpringBoot服務(wù)的注冊(cè)中心和配置中心,本例將在配置文件中配置一個(gè)?cml.age=100?的配置項(xiàng),程序中編寫(xiě)一個(gè)方法讀取配置文件,并通過(guò)?Get--->/test/age?接口提供給瀏覽器訪問(wèn),感興趣的朋友跟隨小編一起看看吧2022-01-01

