Java調(diào)用C++動態(tài)庫超詳細(xì)步驟講解(附源碼)
在某些項目中需要在Java工程中調(diào)用自定義的C++的動態(tài)庫,分為以下兩步,第一步:動態(tài)庫生成;第二步:Java調(diào)用動態(tài)庫。
一、直接調(diào)用C++庫
第一步:動態(tài)庫生成(vs2017+qt5.12.10)
1、新建工程時,一定要選擇qt下的Qt Class Library 這個選項,如下圖所示
2、工程創(chuàng)建成功后,可以在解決方案下看到有testLib.h、testLib.cpp和testlib_global.h三個基礎(chǔ)的文件生成,如下圖所示
3、下面我們簡單寫一個打印“vs2017+qt5.12.10生成動態(tài)庫”的輸出函數(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: 無 * @param-out : 無 * @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,否則中文輸出會亂碼*/ qDebug() << QStringLiteral("vs2017+qt5.12.10生成動態(tài)庫"); return true; }
注:java調(diào)用的c++動態(tài)庫和Python調(diào)用的動態(tài)庫有不同的地方,在于接口的命名方式上,c++中接口命名必須以Java+JavaClassName+接口名,如:Java_SDK_PrintfString。
4、下面我們可以編譯生成動態(tài)庫
第二步:Java調(diào)用C++動態(tài)庫
1、打開vs code 并在動態(tài)庫目錄下新建一個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,如下所示
注:如果運行提示找不到動態(tài)庫,將對應(yīng)的動態(tài)庫和對應(yīng)依賴的庫拷貝到Java執(zhí)行目錄bin下面。
二、調(diào)用帶參數(shù)傳遞的C++庫
在大多數(shù)情況下,我們使用動態(tài)庫調(diào)用時,都涉及參數(shù)傳遞,以下是簡單的參數(shù)傳遞列子。
注:在封裝傳參數(shù)的接口給Java使用時,需要使用到Java對C++提供的參數(shù)名,因此需要將java安裝目錄下的include文件夾拷貝到工程中,并在工程中添加jni.h文件(重之重‘~_~)
第一步:動態(tài)庫封裝
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 : 參數(shù)傳遞 * @param-in: num:數(shù)量,str;字符串 * @return :字符串長度 * @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++傳參的動態(tài)庫,命名規(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就是初始化虛擬機得到的JNI環(huán)境;
參數(shù)jobject _obj為該類的對象;
參數(shù)const jint num位參數(shù)1;
參數(shù)const jstring str為參數(shù)2。
其中(jint、jstring為jni.h文件中,對應(yīng)Java中的int和string)
test.cpp
#include "testLib.h" testLib::testLib() { } bool testLib::Java_SDK_PrintfString() { /*使用QStringLiteral,否則中文輸出會亂碼*/ qDebug() << QStringLiteral("vs2017+qt5.12.10生成動態(tài)庫"); 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、編譯生成動態(tài)庫
第二步:Java調(diào)用C++動態(tài)庫
1、打開vs code 并在動態(tài)庫目錄下新建一個test.java文件
test.java
public class SDK { // 聲明native方法 public native boolean PrintfString(); public native int dataInputAndOutput(int num, String str); // 加載庫 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); 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,如下所示
注:如果運行提示找不到動態(tài)庫,將對應(yīng)的動態(tài)庫和對應(yīng)依賴的庫拷貝到Java執(zhí)行目錄bin下面。
總結(jié)
到此這篇關(guān)于Java調(diào)用C++動態(tài)庫的文章就介紹到這了,更多相關(guān)Java調(diào)用C++動態(tài)庫內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java學(xué)生信息管理系統(tǒng)設(shè)計(數(shù)據(jù)庫版)
這篇文章主要為大家詳細(xì)介紹了數(shù)據(jù)庫版的Java學(xué)生信息管理系統(tǒng)設(shè)計,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-11-11SpringData JPA基本/高級/多數(shù)據(jù)源的使用詳解
這篇文章主要介紹了SpringData JPA基本/高級/多數(shù)據(jù)源的使用詳解,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-02-02Java實現(xiàn)公用實體類轉(zhuǎn)Tree結(jié)構(gòu)
這篇文章主要為大家介紹了一個Java工具類,可以實現(xiàn)Java公用實體類轉(zhuǎn)Tree結(jié)構(gòu),文中的示例代碼簡潔易懂,感興趣的小伙伴可以參考一下2024-10-10