天天看點

c++調用dll_Yolo-v3目标檢測—Java調用C++(JNI)

c++調用dll_Yolo-v3目标檢測—Java調用C++(JNI)

前言

其實這篇文章重點在如何用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

c++調用dll_Yolo-v3目标檢測—Java調用C++(JNI)

添加必須的頭檔案:

jni.h com_xxx_ai_image_detection_service_sdk_DarknetJavaSDK.h
jni.h通常在jdk的include目錄下,如我的:C:Program FilesJavajdk1.8.0_151include

VC++目錄下設定包含路徑:

jni.h依賴的路徑:

C:Program FilesJavajdk1.8.0_151include

C:Program FilesJavajdk1.8.0_151includewin32

c++調用dll_Yolo-v3目标檢測—Java調用C++(JNI)

在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,是以其順序放在最後。

c++調用dll_Yolo-v3目标檢測—Java調用C++(JNI)

然後再添加@Service注解,讓其可以作為一個service被Autowired,改造後的DarknetJavaSDK.java:

package 
           

效果示範:

Java接口調用本地方法:detect_image()

c++調用dll_Yolo-v3目标檢測—Java調用C++(JNI)

傳回檢測出的目标數量20、在指定dirPath下生成檢測圖檔:

c++調用dll_Yolo-v3目标檢測—Java調用C++(JNI)
整個過程參考過如下文章: 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
下一篇: optgroup

繼續閱讀