前言
其實這篇文章重點在如何用Java的JNI調用C++的dll,記錄一下,避免以後自己忘了.....
原文發表在語雀文檔上,排版更美觀
簡介
JNI—摘自百度百科
JNI是Java Native Interface的縮寫,它提供了若幹的API實作了Java和其他語言的通信(主要是C&C++)。從Java1.1開始,JNI标準成為java平台的一部分,它允許Java代碼和其他語言寫的代碼進行互動。JNI一開始是為了本地已編譯語言,尤其是C和C++而設計的,但是它并不妨礙你使用其他程式設計語言,隻要調用約定受支援就可以了。使用java與本地已編譯的代碼互動,通常會喪失平台可移植性。但是,有些情況下這樣做是可以接受的,甚至是必須的。例如,使用一些舊的庫,與硬體、作業系統進行互動,或者為了提高程式的性能。JNI标準至少要保證本地代碼能工作在任何Java 虛拟機環境。
由于近期在玩yolo、darknet,C++項目下的圖像識别(目标檢測),想嘗試下将生成的dll提供給Java服務端調用,于是就有了本篇文章~記個流水賬怕以後自己忘了....
流程
整體來說,要直接将dll被java調用是不可能的,因為兩種語言基本資料類型、方法定義這些是不同的,是以需要用VS建立一個dll項目,生成java項目中可調用的dll。
1.建立native接口方法類
在Java項目中任意位置建立一個類,聲名需要用到的native方法,凡是用native修飾的方法,都是後面調用的dll中的方法(C++實作),static塊中System.load方法即可實作加載dll,在剛開始這部分可以忽略不寫,等VS生成dll後再過來添加。
DarknetJavaSDK.java
package
2.生成.h頭檔案
生成頭檔案時,因為DarknetJavaSDK.java檔案從屬于包:
package com.xxx.ai.image.detection.service.sdk;是以,需要cd到.../src/main/java目錄下(即com/xxx/ai的上一級目錄),運作:
javah com.xxx.ai.image.detection.service.sdk.DarknetJavaSDK即可在目前目錄下生成.h檔案:com_xxx_ai_image_detection_service_sdk_DarknetJavaSDK.h
特别注意:如果目前類:DarknetJavaSDK.java 中有依賴其他你自定義的Java類,則可能報錯,因為類加載的路徑中找不到。解決方法:指定-classpath到.../src/main/java目錄下,這樣即可加載到此路徑下com包下的所有依賴類
例如:javah -classpath D:personalProjectAIimagedetectionsrcmainjava com.flowingbit.ai.image.detection.service.sdk.DarknetJavaSDK
/* DO NOT EDIT THIS FILE - it is machine generated */
4.VS建立dll項目
我的項目:DarknetDllForJava
添加必須的頭檔案:
jni.h com_xxx_ai_image_detection_service_sdk_DarknetJavaSDK.hjni.h通常在jdk的include目錄下,如我的:C:Program FilesJavajdk1.8.0_151include
VC++目錄下設定包含路徑:
jni.h依賴的路徑:C:Program FilesJavajdk1.8.0_151include
C:Program FilesJavajdk1.8.0_151includewin32
在DarknetDllForJava.cpp定義.h的導出函數
// DarknetDllForJava.cpp : 定義 DLL 應用程式的導出函數。
建立導出函數頭檔案dll_api.h
#pragma once
建立dll_api.cpp,定義函數實作
這裡就是按照dll_api.h裡的函數定義,編寫其實作,需要注意的是,需要添加#include
然後,Java中的基本資料類型和C++中的有些是需要互相轉化的,如:
jboolean表示java中的布爾值true和false,在c++中對應的是JNI_FALSE和JNI_TRUE;
jstring表示java中的String類,jstring和c++中的string類的互相轉化可以用以下函數:
jstring
5.生成dll,并在Java中加載
第4.步驟完成後,生成的dll時可以直接被java加載利用的,隻需要在DarknetJavaSDK.java中用
_
System.*load(YOUR_*DLL_PATH);_即可完成dll加載工作,順序不正常會報錯。。。
以我的為例:
DarknetDllForJava.dll是第4.步建立的dll項目生成的dll,其運作依賴上面三個dll,是以其順序放在最後。
然後再添加@Service注解,讓其可以作為一個service被Autowired,改造後的DarknetJavaSDK.java:
package
效果示範:
Java接口調用本地方法:detect_image()
傳回檢測出的目标數量20、在指定dirPath下生成檢測圖檔:
整個過程參考過如下文章: https:// blog.csdn.net/qq_382881 72/article/details/82387946 https://www. jb51.net/article/132930 .htm https://www. cnblogs.com/haitaofeiya ng/p/7698121.html