c++调用dll_Yolo-v3目标检测—Java调用C++(JNI)

2ef7436432375c18047241a3a943a974.png

前言

其实这篇文章重点在如何用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

0b17a5a6c87d2714087a118cbc3d3926.png

添加必须的头文件:

jni.hcom_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

6cb1d8eeebe5df40bb15d19e7156b04f.png

在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,所以其顺序放在最后。

346fdb36f8650447265469d58760f4f1.png


然后再添加@Service注解,让其可以作为一个service被Autowired,改造后的DarknetJavaSDK.java:

package 

效果演示:

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

5b58778fc913a045f76b777f6a132396.png


返回检测出的目标数量20、在指定dirPath下生成检测图片:

27b1e007f68f535b3443ead1ca2e1677.png
整个过程参考过如下文章: 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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值