本文主要是介绍Java调用C++动态库超详细步骤讲解(附源码),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
《Java调用C++动态库超详细步骤讲解(附源码)》C语言因其高效和接近硬件的特性,时常会被用在性能要求较高或者需要直接操作硬件的场合,:本文主要介绍Java调用C++动态库的相关资料,文中通过代...
在某些项目中需要在Java工程中调用自定义的C++的动态库,分为以下两步,第一步:动态库生成;第二步:Java调用动态库。
一、直接调用C++库
第一步:动态库生成(vs2017+qt5.12.10)
1、新建工程时,一定要选择qt下的Qt Class Library 这个选项,如下图所示
2、工程创建成功后,可以在解决方案下看到有testLib.h、testLib.cpp和testlib_global.h三个基础的文件生成,如下图所示
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++动态库
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执行目录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++动态库
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执行目录bin下面。
总结
到此这篇关于Java调用C++动态库的文章就介绍android到这了,更多相关Java调用C++动态库内容请搜索China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程China编程(www.chinasem.cn)!
这篇关于Java调用C++动态库超详细步骤讲解(附源码)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!