1、背景
最近接手的项目,底层算法是C++写的,并且封装成了dll。而目前的需求,需要把这些算法移到服务端执行。不可能把C++写的算法库改用Java重写一遍,而且也基于执行效率的考虑,采用Java调用dll的方案
2、依赖包
添加依赖如下:
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>5.7.0</version>
</dependency>
3、常见的写法
查资料,经常见到如下的实现
import com.sun.jna.Library;
import com.sun.jna.Native;
public class XXXX {
...
public interface JnaDll extends Library {
int funname(String content);
JnaDll jnaDll = (JnaDll)Native.load("D:\\xx\\...\\xx", JnaDll.class);
}
...
public void xxxx() {
int result = JnaDll.jnaDll.funname("xxx");
...
}
}
4、局限性
可以看到,dll路径是写死在代码里的。
如果需要将dll路径放到配置文件中怎么办?即需要放到application-xxx.yml中。
5、解决方案
我们可以把dll的方法封装成Java服务,如下:
import com.sun.jna.Library;
import com.sun.jna.Native;
@Service
public class XXXX {
@Value("${xx.xx}")
private String dllPath;
...
private interface JnaDll extends Library {
int funname(String content);
int funname2(Pointer pointer);
}
JnaDll jnaDll;
private JnaDll getJnaDll() {
if (jnaDll == null) {
jnaDll = (JnaDll)Native.load(this.dllPath, JnaDll.class);
}
return jnaDll;
}
...
public void xxxx() {
int result = getJnaDll().funname("xxx");
...
}
}
6、分析
(1)代码中的接口JnaDll其实只是个申明,是dll中C方法的封装,这个接口只在当前类中有效即可,所以可以申明为私有接口
(2)相应的变量在哪里都可以申明和实例化,不一定只能属于该接口,也不一定只能申明时实例化
7、参数说明
(1)从dll中返回字符串,接口定义返回类型为const char*,没成功,只好将传入参数类型改为char*,而Java中对接的参数为Pointer。
调用方法传参前,要保存空间足够,写法如下:
Pointer pointer = new Memory(xxxx);
getJnaDll().funname2(pointer);
(2)只是给dll传入const char*,不需要dll返回字符串,则传入String即可。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)