JNA---使用Java代码调用c/c++编译生成的.so文件
使用Java代码调用c/c++编译生成的.so文件
公司项目中多个组使用的开发语言不一致,在项目主分支使用的是Java开发的springboot项目,但是需要用到的OCR识别功能是另外一个组开发的c++程序,后面为了使用Java能够调用c++程序,Java去调用c/c++程序是可以调用的,现在流行的技术有jni和jna等。
JNI技术使用起来很麻烦,我们这次使用也放弃了这种方式来实现而是采用了JNA方式来实现Java代码封装c++代码生成的.so文件:
首先,在pom.xml文件中新增jna依赖包:
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>5.5.0</version>
</dependency>
然后,编写一个JNA的工具类:JnaUtil:
在这个类中有一个继承Library的公共接口Clibrary后续的c++函数的调用要通过此公共接口进行,在此工具类中有三个封装so的函数对应于c++的三个函数,如下图所示:
在JnaUtil类中还有个重要的东西,一个CLibrary类型的INSTANCE,用来进行so动态库加载,使用方式如下:
CLibrary INSTANCE = (CLibrary) Native.load("imageocr", CLibrary.class);
其中Native.load函数,第一个参数“imageocr”,这个参数是so文件libimageocr.so的名称的简写,后续使用c++的函数可以通过INSTANCE进行调用,如所示:
Pointer pHandleOCR = JnaUtil.CLibrary.INSTANCE.InitializeModels_V1(MODEL_CFG);
String txtPath = JnaUtil.CLibrary.INSTANCE.ImageOCR_V1(pathFile, modeType, pHandleOCR);
JnaUtil.CLibrary.INSTANCE.FreeModels_V1(pHandleOCR);
还有一点是需要注意的,部署到Linux服务器上时需要进行动态库的路径设置,需要修改/etc/profile文件,在文件最后增加以下内容:
新增JAVA_HOME、CLASSPATH、PATH、export JAVA_HOME CLASSPATH PATH、export LD_LIBRARY_PATH=/root,其中export LD_LIBRARY_PATH=/root代表so动态库libimageocr.so的所在的路径,最后要立即生效此修改,执行;以下命令source /etc/profile。
至此,使用JNA进行Java程序调用c/c++程序的小实践就结束了,希望能够帮助正好要有此类需要的朋友。