JNA的使用
>>版权声明:本文为原创文章,请不要拷贝转载。
1.JNA资料
https://github.com/java-native-access/jna
这份说明中讲的还是蛮细的,参数映射,指针,回调函数等等都有涉及,源码中还有一些例子。
2.使用例子
- 引入依赖
<dependency> <groupId>net.java.dev.jna</groupId> <artifactId>jna</artifactId> <version>5.3.1</version> </dependency>
- 新建接口类来加载Native库,映射库中方法
public interface MsvcrtLibrary extends Library { //加载动态库 MsvcrtLibrary INSTANCE = (MsvcrtLibrary)Native.load("msvcrt"), MsvcrtLibrary.class); void printf(String format, Object... args); }
这个是文档中的例子,它在windows下会加载了msvcrt.dll库。
msvcrt.dll在系统库目录中,可见JNA会自动搜素系统库目录。
- 调用native方法
public class HelloWorld { public static void main(String[] args) { MsvcrtLibrary.INSTANCE.printf("Hello, World\n"); } }
3.注意事项
- 动态库搜素加载的路径
指定设置搜素路径的方式:
- 可以通过设置系统属性“jna.library.path”
- 修改系统的库访问环境变量
- 将库放置在classpath下,或者放在{OS}-{ARCH}/目录下,比如win32-x86,win32-x86-64,linux-x86-64,linux-x86,linux-amd64,darwin等。如果放在jar文件中,则会在加载时自动提取。
建议自定义的本地库,打入jar包中,可以参考JNA.jar
- CLibrary、StdCallLibrary、Library
CLibrary支持基于*nix的操作系统,比如各种Unix的分支和Linux等。
StdCallLibrary支持windows操作系统。
使用时如果继承了错误的Library基类,会报Unrecognized calling convention错误。所以建议都继承于Library。
- 并发调用
JNA支持多线程并发调用。在com.sun.jna.Library接口中有说明。
4.参数映射
参数映射问题在跨语言调用中比较麻烦,好在JNA有所考虑,下面是基础类型和字符串的对应关系。
https://github.com/java-native-access/jna/blob/master/www/Mappings.md
指针和数组可以用java的数组表示,但是java基础类型的数组只在函数调用范围内起作用,超出该返回则必须使用com.sun.jna.Memory和NIO direct Buffer了。
char* argv[]可以用String[]表示。
char* argv用byte[],ByteBuffer,String表示。在表示回参时,使用byte[]和ByteBuffer表示。
c的enum可以用int替换。