Java 调用 C/C++ 之 JNA 系列实战篇 —— 起步 (一)

一、为什么要写这篇文章         

        最近单位开发一些项目,要用到Java 调用 C/C++ 动态链接库,我采了JNA的调用方式,同时在开发过程中遇到过一些问题,但上网查找,发现对JNA的介绍不多,大部分只是一个初级入门,所以结合自己的实际开发,把总结出来的知识点及问题与大家分享下。在Windows 平台与 Linux平台都实现了。


二、为什么选用JNA

       Java 调用 C/C++ 动态链接库,有两种方式 JNI 与 JNA,它们的原理一样,但使用起来难易度却有区别,做个对比:

      1. JNI 比JNA难度要高一些,因为JNI要根据Java代码生成头文件,生成特殊的方法签名。再针对头文件定义的函数,用JNI 语法结合C/C++语法来实现函数,在函数中再去调用动态链接库,在这个过程中还需要去管理内存的问题(有一篇文章给大家推荐下:在 JNI 编程中避免内存泄漏)。而JNA方式完全省略了这一复杂过程。使用方便是JNA的一大特点。

         2. JNI 可以实现Java 调用 C/C++,同时 C/C++也可调用Java 。但JAN却只能Java 调用 C/C++,不具备反向调用。刚好在项目中不要用到C/C++调用JAVA,所以选择了JNA的方式。


三、 环境申明

          环境没有配好,会出现许多错误,如:找不到库文件,无法加载库文件等等,如果是刚上手,一时会找不到出错点。

我实际项目中用到的环境是(已经设置好了jdk的环境,另外在Linux平台上还要加设一变量LD_LIBRARY_PATH,它的值要等于你即将调用的so文件存放的目录,我习惯把so文件存在我的项目直接目录下,路径也就指向项目目录):

      1. windows (64位), JDK (64位),dll文件 (64位)

      2. Linux (64位),      JDK (64位),so文件 (64位)

      我的意思是要用 64位的JDK去调用64位的dll/so 文件; 32位的JDK去调用32位的dll/so 文件,如果不对应则会生如下异常信息:

      异常一:如在windows平台,用64位jdk 调用 32位的dll :Exception in thread "main" java.lang.UnsatisfiedLinkError: Unable to load library 'XxxEngine': Native library (win32-  x86-64/XxxEngine.dll) not found in resource path,它是意思是没有找到64位的dll文件,它需要的是64的文件。

      异常二:我在Linux平台上还发现有这样一个异常:Exception in thread "main" java.lang.UnsatisfiedLinkError: Unable to load library 'XxxEngine': Native library (linux-x86-64/libKwsEngine.so) not found in resource path,而我已经保证了64位的JDK调用64位的so 文件,并且Linux也是64位的操作系统,经过一番查找,是因为libXxxEngine.so文件内部引用了另外的so文件,把的依赖的文件加入就可以解决问题了,如放在/usr/local/lib 下面,此为系统默认查找库资源的路径。如何查看一个so文件依赖其它的文件方式是:ldd libXxxEngine.so。如果确定环境不再有问题,也执行过ldconfig命令,则重新启动下电脑试试。


三、官方JNA

      JNA的官方资源路径为https://github.com/twall/jna/,在这里可以下载 jna.jar 文件,以及可以查看文档JavaDoc,开发时一定要查看文档,因以它里面介绍了C Type 对应到 Java Type 数据类型。如下图



四、开发结构

        1.  把需要调用的dll/so文件放到项目的根目录下,如下图在linux环境下面libTestCF.so (在linux 下面要设置环境变量:LD_LIBRARY_PATH=/root/workspace/HelloJNA , Windows下面不用设置此环境变量),在linux下的文件为libTestCF.so,在windows下面为TestCF.dll

         

         

       2. 在libTestCF.so有要被调用的函数,在cf.h头文件有如下申明:采用C语言形式接口函数      

extern "C"
{
	Public  int TestReadCF();
}
      3. 根据头文件编写Java代码:如图


                

     Java代码为:

package cn.jna.test;


import com.sun.jna.Library;
import com.sun.jna.Native;

public interface CFJna extends Library {

	//加载动态资源库
	CFJna library = (CFJna) Native.loadLibrary("TestCF", CFJna.class);//注意库名称的写法不要含有lib字符
	
	//定义要调用的方法,与cf.h头文件中定义的函数名一样
	int TestReadCF();
}

          4. 测试调用,如下图:


               java 代码:

package cn.jna.test;

public class CFJnaTest {

	public static void main(String[] args) {

		int testReadCF = CFJna.library.TestReadCF();
		System.out.println("testReadCF:"+testReadCF);
	}

}

 收尾 JNA调用还是很方便上手的, 在接下来的文章我将会把我实际开发中应用到的知识与 大家分享,请继续关注,或关注我的新浪微博:微博Abel




  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值