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:

               JNA---使用Java代码调用c/c++编译生成的.so文件

      在这个类中有一个继承Library的公共接口Clibrary后续的c++函数的调用要通过此公共接口进行,在此工具类中有三个封装so的函数对应于c++的三个函数,如下图所示:

    JNA---使用Java代码调用c/c++编译生成的.so文件

在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文件,在文件最后增加以下内容:

JNA---使用Java代码调用c/c++编译生成的.so文件

新增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++程序的小实践就结束了,希望能够帮助正好要有此类需要的朋友。