代码告诉你:Java到底是怎么调用dll&so动态库的?

使用Java调用dll&so动态库的函数

*应用背景:项目中需要调用一项其他平台提供的服务,是一位C语言老大哥写的,可牛啦。但是因为一些特殊原因导致不能通过API调用的方式实现,最终的解决方案是老大哥把他的程序封装成so和dll动态库,然后我在项目里使用JNA调用so或dll动态库里的函数。

1.在pom.Xml里建立JNA框架依赖

<dependency>
		    <groupId>net.java.dev.jna</groupId>
		    <artifactId>jna</artifactId>
		    <version>4.1.0</version>
</dependency>

2.在Windows系统调用.dll动态库
*作者是在Windows系统做开发的,所以在本机调试的时候让C的老大哥给我封装了个dll文件使用,方便你我他。
(1).代码实现
java调用dll文件
(2).dll文件的位置如下图:
dll文件位置

3.在linux系统调用.so动态库
*项目开发完成后,部署到测试环境,我们的测试环境用的linux,所以老大哥又登录我们的测试服务器熟练的封装了so文件。
(1).代码实现,与调用.dll文件基本一致
java调用so文件,红框重点
(2).so文件的位置如下图:这个文件必须等项目打成的war包解压后手动放到classes目录下,如果放在项目的resources目录下直接打成war包使用,有可能会损坏so文件。
so文件位置
另外,我们的so文件在初始化时,内部加载了其他的资源,这个资源位置必须在服务器的执行目录下,我们使用的tomcat,所以就放在了tomcat的bin目录下

4.java和c的类型映射
接口中使用的函数必须与链接库中的函数原型保持一致,这是JNA甚至所有跨平台调用的难点,因为C/C++的类型与Java的类型是不一样的,你必须转换类型让它们保持一致!
JNA官方给出的默认类型映射表如下:
类型映射
5.最后的源码留给你们

public interface CLibrary extends Library {

	//linux系统调用.so文件,libline.so文件一般放在编译后的classes目录下。注意,这里只要写line就可以
	了,不要写libline,也不要加后缀
	
	CLibrary INSTANCE = (CLibrary)Native.loadLibrary("line", CLibrary.class);

    Void printf(String format);//对应.so文件内封装的函数
}

public static void main(String[] args) {
    CLibrary.INSTANCE.printf("test");
}

注:JNA是建立在JNI技术基础之上的一个Java类库,它使您可以方便地使用java直接访问动态链接库中的函数。原来使用JNI,你必须手工用C写一个动态链接库,在C语言中映射Java的数据类型,说白了就是得多写一堆C代码。JNA中,它提供了一个动态的C语言编写的转发器,可以自动实现Java和C的数据类型映射,你不再需要编写C动态链接库。也许这也意味着,使用JNA技术比使用JNI技术调用动态链接库会有些微的性能损失。但总体影响不大,因为JNA也避免了JNI的一些平台配置的开销。

猜你喜欢

转载自blog.csdn.net/weixin_43945983/article/details/84791981