欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java通過JNI調(diào)用C++動態(tài)庫的完整流程詳解

 更新時間:2025年04月09日 09:17:10   作者:頗有幾分姿色  
JNI(Java Native Interface),是實現(xiàn)Java/Kotlin與C/C++語言之間交互的橋梁,本文主要為大家介紹了Java通過JNI調(diào)用C++動態(tài)庫的完整流程,需要的可以參考下

介紹使用 JNI 調(diào)用 C++ 編寫的動態(tài)鏈接庫的全過程。

示例環(huán)境

項目說明
JDK8
C++ 編譯器Visual Studio 2019
Java 開發(fā)工具IntelliJ IDEA 2021.3
操作系統(tǒng)Windows 10

Java 項目結(jié)構(gòu)概覽

編寫 Java 類

在 org.jni.nativejni 包下創(chuàng)建類 HelloWorldJni.java:

package org.jni.nativejni;

public class HelloWorldJni {

    static {
        // 加載 C++ 編譯生成的 DLL
        System.load("E:/vsproject/HelloWorld/x64/Release/HelloWorld.dll");
    }

    // native 方法聲明
    public native String sayHello(String str1, String str2);
    public native int add(int a, int b);

    public static void main(String[] args) {
        HelloWorldJni hw = new HelloWorldJni();
        System.out.println("拼接字符串:" + hw.sayHello("Hello", "World"));
        System.out.println("相加:" + hw.add(52, 23));
    }
}

生成 JNI 頭文件

方法一:使用 javac -h(推薦方式,支持 JDK8+)

在項目根目錄下執(zhí)行命令:

javac -h src/main/jni src/main/java/org/jni/nativejni/HelloWorldJni.java

說明:

  • -h 參數(shù)用于指定生成頭文件的目錄。
  • 這個命令會編譯 .java 文件然后生成 .class 文件,同時生成 JNI 頭文件。

注意:這個命令會在源碼目錄中生成 .class 文件,建議在 target/classes 中操作,避免污染源碼。

方法二:使用 javah(僅適用于 JDK8)

先使用 Maven 編譯項目:

mvn clean install

然后執(zhí)行:

javah -classpath target/classes -d src/main/jni org.jni.nativejni.HelloWorldJni

說明:

  • -classpath 指定 .class 文件的根路徑。
  • -d 指定 JNI 頭文件的輸出目錄。

實現(xiàn) JNI 層與調(diào)用 DLL 方法

使用 Visual Studio 編譯生成 DLL

1.創(chuàng)建一個新的 C++ DLL 項目,項目名稱為 HelloWorld。

2.添加源文件:

  • HelloWorld.cpp:實現(xiàn) DLL 的原始功能邏輯。
  • HelloWorldJNI.cpp:實現(xiàn) JNI 橋接代碼。

3.配置項目屬性:

C/C++ → 常規(guī) → 附加包含目錄中添加:

  • JDK 的 include 目錄
  • JDK 的 include/win32 目錄

C++ 頭文件:HelloWorld.h

#ifndef HELLO_WORLD_H
#define HELLO_WORLD_H

// 導出 HelloWorld 函數(shù)
extern "C" __declspec(dllexport) const char* HelloWorld(const char* str1, const char* str2);

// 導出 Add 函數(shù)
extern "C" __declspec(dllexport) int Add(int a, int b);

#endif // HELLO_WORLD_H#pragma once

C++ 實現(xiàn):HelloWorld.cpp

// HelloWorld.cpp
#include "pch.h" // 如果 VS 生成了預編譯頭文件
#include "HelloWorld.h" // 引入頭文件
#include <iostream>
#include <string>

extern "C" __declspec(dllexport) const char* HelloWorld(const char* str1, const char* str2) {
    static std::string result; // 使用靜態(tài)變量存儲返回值,確保返回的指針有效
    result = std::string(str1) + "," + std::string(str2);
    return result.c_str(); // 返回拼接后的 C 字符串
}

// 一個簡單的加法函數(shù)
extern "C" __declspec(dllexport) int Add(int a, int b) {
    return a + b;
}

JNI 頭文件:org_jni_nativejni_HelloWorldJni.h

由 javac -h 或 javah 自動生成,內(nèi)容如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class org_jni_nativejni_HelloWorldJni */

#ifndef _Included_org_jni_nativejni_HelloWorldJni
#define _Included_org_jni_nativejni_HelloWorldJni
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     org_jni_nativejni_HelloWorldJni
 * Method:    sayHello
 * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_org_jni_nativejni_HelloWorldJni_sayHello
  (JNIEnv *, jobject, jstring, jstring);

/*
 * Class:     org_jni_nativejni_HelloWorldJni
 * Method:    add
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_org_jni_nativejni_HelloWorldJni_add
  (JNIEnv *, jobject, jint, jint);

#ifdef __cplusplus
}
#endif
#endif

JNI 實現(xiàn):HelloWorldJNI.cpp

#include "pch.h" // 如果 VS 生成了預編譯頭文件
#include "org_jni_nativejni_HelloWorldJni.h"  // 引入自動生成的 JNI 頭文件
#include "HelloWorld.h"    // 引入自定義的頭文件,調(diào)用已有的 DLL 接口

JNIEXPORT jstring JNICALL Java_org_jni_nativejni_HelloWorldJni_sayHello
(JNIEnv* env, jobject, jstring jStr1, jstring jStr2) {
    // 將 Java 字符串轉(zhuǎn)換為 C 字符串
    const char* str1 = env->GetStringUTFChars(jStr1, nullptr);
    const char* str2 = env->GetStringUTFChars(jStr2, nullptr);

    // 調(diào)用 C++ 動態(tài)庫函數(shù)
    const char* result = HelloWorld(str1, str2);

    // 釋放 Java 字符串的本地內(nèi)存
    env->ReleaseStringUTFChars(jStr1, str1);
    env->ReleaseStringUTFChars(jStr2, str2);

    // 將 C 字符串轉(zhuǎn)換為 Java 字符串并返回
    return env->NewStringUTF(result);
}


JNIEXPORT jint JNICALL Java_org_jni_nativejni_HelloWorldJni_add
(JNIEnv*, jobject, jint a, jint b) {
    return Add(a, b); // 調(diào)用原始的 Add 函數(shù)
}

提示:這里為了演示方便,JNI 橋接代碼和業(yè)務邏輯放在同一個項目中。實際開發(fā)時橋接層要單獨封裝,便于維護與復用。

Java 調(diào)用 DLL 測試

將編譯生成的 HelloWorld.dll 放到系統(tǒng)環(huán)境變量中,這里這個庫沒什么其他依賴,都是系統(tǒng) c 盤中有的,所以直接指到它生成的目錄就可以使用了。

運行 Java 主類的輸出結(jié)果:

拼接字符串:Hello,World
相加:75

總結(jié)

梳理一下 Java 調(diào)用 C++ DLL 的完整流程。主要包括:

  • 編寫 Java 類并聲明 native 方法
  • 使用 javac -h 或 javah 生成 JNI 頭文件
  • 實現(xiàn) JNI 橋接層,調(diào)用 DLL 中的 C++ 方法
  • 使用 Visual Studio 生成 DLL 文件
  • Java 運行時加載并調(diào)用本地方法,或者封裝成接口給別人使用。

到此這篇關于Java通過JNI調(diào)用C++動態(tài)庫的完整流程詳解的文章就介紹到這了,更多相關Java JNI調(diào)用C++動態(tài)庫內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • mybatis實現(xiàn)批量插入并返回主鍵(xml和注解兩種方法)

    mybatis實現(xiàn)批量插入并返回主鍵(xml和注解兩種方法)

    這篇文章主要介紹了mybatis實現(xiàn)批量插入并返回主鍵(xml和注解兩種方法),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • 如何給yml配置文件的密碼加密(SpringBoot)

    如何給yml配置文件的密碼加密(SpringBoot)

    這篇文章主要介紹了如何給yml配置文件的密碼加密(SpringBoot),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • Java如何Mock FileInputStream問題

    Java如何Mock FileInputStream問題

    這篇文章主要介紹了Java如何Mock FileInputStream問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • 淺談Spring中HandlerMapping的使用

    淺談Spring中HandlerMapping的使用

    這篇文章主要介紹了淺談Spring中HandlerMapping的使用,Spingmvc中的HandlerMapping負責解析請求URL,對應到Handler進行處理,這里的Handler一般為Controller里的一個方法method,也可以為servlet或者Controller等,需要的朋友可以參考下
    2023-08-08
  • Springboot項目javax.validation使用方法詳解

    Springboot項目javax.validation使用方法詳解

    這篇文章主要介紹了Springboot項目javax.validation使用方法詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-04-04
  • java正則表達式匹配網(wǎng)頁所有網(wǎng)址和鏈接文字的示例

    java正則表達式匹配網(wǎng)頁所有網(wǎng)址和鏈接文字的示例

    這篇文章主要介紹了java正則表達式匹配網(wǎng)頁所有網(wǎng)址和鏈接文字java正則表達式匹配,需要的朋友可以參考下
    2014-03-03
  • Java虛擬機底層原理詳細分析

    Java虛擬機底層原理詳細分析

    這篇文章主要介紹了Java虛擬機底層原理詳細分析,運行時數(shù)據(jù)區(qū)就是俗稱的虛擬機內(nèi)存,主要包括我們熟悉的堆、棧、本地方法棧、方法區(qū)(元空間)、程序計數(shù)器,虛擬機調(diào)優(yōu)主要針對的是運行時數(shù)據(jù)區(qū),也就是虛擬機內(nèi)存,需要的朋友可以參考下
    2024-01-01
  • JAVA調(diào)用JavaScript方法代碼示例

    JAVA調(diào)用JavaScript方法代碼示例

    之前在一次機緣巧合的情況下,需要時用JAVA執(zhí)行js方法,查閱了一些文檔,找到了相關解決方法,這里和大家分享一下,這篇文章主要給大家介紹了關于JAVA調(diào)用JavaScript方法的相關資料,需要的朋友可以參考下
    2023-09-09
  • Java8實戰(zhàn)之Stream的延遲計算

    Java8實戰(zhàn)之Stream的延遲計算

    JDK中Stream的中間函數(shù)如 filter(Predicate super T>)是惰性求值的,filter并非對流中所有元素調(diào)用傳遞給它的Predicate,下面這篇文章主要給大家介紹了關于Java8實戰(zhàn)之Stream延遲計算的相關資料,需要的朋友可以參考下
    2021-09-09
  • Java實現(xiàn)在線編輯預覽office文檔詳解

    Java實現(xiàn)在線編輯預覽office文檔詳解

    PageOffice是一款在線的office編輯軟件,幫助Web應用系統(tǒng)或Web網(wǎng)站實現(xiàn)用戶在線編輯Word、Excel、PowerPoint文檔,下面我們就來看看如何使用Java實現(xiàn)在線預覽office吧
    2024-01-01

最新評論