JNA调用C动态库dll、so
来源:互联网 发布:php 防止sql注入 编辑:程序博客网 时间:2024/04/28 07:49
1.介绍jna
优点
JNA可以让你像调用一般java方法一样直接调用本地方法。就和直接执行本地方法差不多,而且调用本地方法还不用额外的其他处理或者配置什么的,也不需要多余的引用或者编码,使用很方便。
与jni对比
在java JDk也有调用动态库的技术:jni,相对jna来说,jna功能给强大,效率更高,但是入门门槛高,它要求调用的函数库是符合jni调用规范的。如果你要调用的函数库不符合jni规范,对不起,你得自己用C写一个符合jni调用规范的函数库,在里面调用要你要使用的函数,然后你再去调用这个jni规范的函数库,实现你的功能。这样的话开发量更大,而且开发难度也更大(要求你会C),但使用jna的话就问题就简单很多了,我不需要你的函数符合jni规范,直接可以调用原生函数库,不需要编写任何Native/JNI代码。
使用jna(jni)的两个缺点:
2.与java数据类型的映射
跨平台、跨语言调用的最大难点,就是不同语言之间数据类型不一致造成的问题。绝大部分跨平台调用的失败,都是这个问题造成的。
JNA使用的数据类型是Java的数据类型。而原生函数中使用的数据类型是原生函数的编程语言使用的数据类型。可能是C,Delphi,汇编等语言的数据类型。因此,不一致是在所难免的。
JNA提供了Java和原生代码的类型映射。
和操作系统数据类型的对应表
Java 类型
C 类型
原生表现
boolean
int
32位整数 (可定制)
byte
char
8位整数
char
wchar_t
平台依赖
short
short
16位整数
int
int
32位整数
long
long long, __int64
64位整数
float
float
32位浮点数
double
double
64位浮点数
Buffer
Pointer
pointer
平台依赖(32或 64位指针)
<T>[] (基本类型的数组)
pointer
array
32或 64位指针(参数/返回值)
邻接内存(结构体成员)
支持常见的数据类型的映射
Java 类型
C 类型
原生表现
String
char*
/0结束的数组 (native encoding or jna.encoding
)
WString
wchar_t*
/0结束的数组(unicode)
String[]
char**
/0结束的数组的数组
WString[]
wchar_t**
/0结束的宽字符数组的数组
Structure
struct*
struct
指向结构体的指针 (参数或返回值) (或者明确指定是结构体指针)
结构体(结构体的成员) (或者明确指定是结构体)
Union
union
等同于结构体
Structure[]
struct[]
结构体的数组,邻接内存
Callback
<T> (*fp)()
Java函数指针或原生函数指针
NativeMapped
varies
依赖于定义
NativeLong
long
平台依赖(32或64位整数)
PointerType
pointer
和 Pointer
相同
尽量使用基本、简单的数据类型;
尽量少跨平台、跨语言传递数据!
3.使用
dll、so函数库区别
dll、so函数库都可以通过jna来调用,dll与so函数库的区别是:dll是C编译windows环境下使用的函数库,而so是在linux等环境下使用的函数库,他们调用的方法都是一样的。
下面是一个调用dll的例子:
函数库libHsMacAPI.h头文件(相对于函数库api)
函数名称: GenZAK 功能描述: 用于生成MACKey 参数说明: sMacKey 存放生成的MACKEY,长度为16位 返回值: 无 void GenZAK(char * sMacKey); ********************************************************************* 函数名称: GenMAC 功能描述: 用于生成MAC 参数说明: sMacBuf 需要进行MAC的数据流 sMac 生成的MAC,最小为16字节 sMacKey 对MAC加密密钥(加密过的KEY) 返回值: 无 ********************************************************************** void GenMAC(char * sMacBuf, char * sMac, char * sMacKey); 函数名称: MACVerify 功能描述: 用于检查MAC 参数说明: sMacBuf 需要进行MAC的数据流 sMac 生成的MAC,最小为16字节 sMacKey 对MAC加密密钥(加密过的KEY) 返回值: =0:校验成功 !=0: 校验不成功 ********************************************************************** int MACVerify(char * sMacBuf, char * sMac, char * sMacKey);
分析:
通过头文件我们可以看到:
1.在GenZAK方法中sMacKey是出参,相当于指针(Pointer),我们将一个指针传入,然后它给我们给我们的指针赋值,在java中我们使用对应的Pointer的子类Memory进行传值。
2.在GenMAC方法中sMacBuf 是入参,char*对应的是java中的String;sMac是出参,对应Memory,sMacKey是入参;对应java中是String,但我们之前定义了为Memory类型,这里我们就不将其转化为String了,还是直接用Memory类型。
3.在MACVerify方法中sMacBuf、sMacKey、sMac都是入参,因为我们之前定义sMacKey、sMac都是Memory类型,所以还是使用Memory类型,sMacBuf还是String类型。
入参使用与java对应的类型即可,出参都需使用指针类。
实现:
需要下载jna架包
1.编写jna接口代码(接口里面的方法名要跟C的接口方法名一致)
<p>package demo;</p><p>import com.sun.jna.Library;import com.sun.jna.Native;import com.sun.jna.Pointer;</p><p>/** * 接口里面的方法名要跟C的接口方法名一致 * 调用linux so(动态库) 获取mac * @since JDK1.6 */public interface LibHsMacAPIJNA extends Library{ /* 然后开始我们的java接口 loadLibrary第一个参数就是你的dll名字 第二个就是当前接口的.class类型 */ //线程安全 (加载lib使用了绝对路径 切割去掉了路径前面的"/") public LibHsMacAPIJNA INATANCE = (LibHsMacAPIJNA) Native.synchronizedLibrary((LibHsMacAPIJNA)Native.loadLibrary(LibHsMacAPIJNA.class.getResource("/libHsMacAPI.dll").getPath().substring(1), LibHsMacAPIJNA.class)); </p><p> /********************************************************************* 函数名称: GenMAC 功能描述: 用于生成MAC 参数说明: sMacBuf 需要进行MAC的数据流 sMac 生成的MAC,最小为16字节 sMacKey 对MAC加密密钥(加密过的KEY) 返回值: 无 **********************************************************************/ public void GenMAC(String sMacBuf, Pointer sMac, String sMacKey); /* 函数名称: GenZAK 功能描述: 用于生成MACKey 参数说明: sMacKey 存放生成的MACKEY,长度为16位 返回值: 无 **********************************************************************/ public void GenZAK(Pointer sMacKey); /********************************************************************* 函数名称: MACVerify 功能描述: 用于检查MAC 参数说明: sMacBuf 需要进行MAC的数据流 sMac 生成的MAC,最小为16字节 sMacKey 对MAC加密密钥(加密过的KEY) 返回值: =0:校验成功 !=0: 校验不成功 **********************************************************************/ public int MACVerify(String sMacBuf, String sMac, String sMacKey);}</p>
Native.loadLibrary()加载函数库文件时,可以直接填写函数库名称(前缀lib可以去掉,后缀也可以去掉),不过前提是这个函数库必须放在系统或者java的函数库目录下;也可以放在任意位置,使用绝对路径。
2.调用函数库代码
package demo;import com.sun.jna.Memory;import com.sun.jna.Pointer;/** * 此类功能描述 * @version 2015-6-1 下午4:13:03 * @since JDK1.6 */public class LibHsMacAPITest {public static void main(String[] args) throws Exception {LibHsMacAPITest.generateMAC();} /** * 生成MAC * @param method * @param databuf * @param datalen * @param key * @return * @throws Exception */ public static void generateMAC() throws Exception{ //获取key Pointer sMacKey = new Memory(100); LibHsMacAPIJNA.INATANCE.GenZAK(sMacKey); String key = new String(sMacKey.getByteArray(0, 100)); System.out.println("key:" + key); //加密 Pointer sMac = new Memory(16); String sMacBuf = new String("1111"); LibHsMacAPIJNA.INATANCE.GenMAC(sMacBuf, sMac, key); String mac = new String(sMac.getByteArray(0, 16),"utf-8"); System.out.println(mac); //检验加密是否正确 int flag = LibHsMacAPIJNA.INATANCE.MACVerify(sMacBuf, mac, key); System.out.println("检验结果:" + (flag == 0 ? "成功":"失败")); }}
4.使用jna注意
注意事项
在非web工程时,将需要调用的函数库文件放置在工程目录下是OK的;但在web工程中,放置在工程目录下是no OK的,因为项目发布时会将函数库也进行编译,造成函数库损坏。故在工程中使用jna,建议放在外部文件中,别放工程目录下。
加载函数库时,使用的绝对路径中不能有中文!
工程地址:http://download.csdn.net/detail/u010722643/8893181
- JNA调用C动态库dll、so
- linux jna调用so动态库
- windows/linux + java + jna + dll/so 调用C/C++
- JNA方式调用dll动态库
- Java框架JNA调用C方法(windows链接库dll文件、linux链接库so文件)
- JNA框架之JNI(JAVA调用DLL/SO库)
- JNA调用C语言动态链接库
- ubuntu下 jna调用so动态链接库
- 使用JNA框架调用dll动态链接库
- Java调用本地库,如调用DLL或者SO,如:JNI, Jawin, Jacob,JNative,JNA
- JNA调用C实现的DLL
- java通过JNA调用c语言dll
- java调用动态库(.dll或.so)
- python 调用so dll动态链接库
- go调用动态链接库dll/so
- Jna调用动态链接库
- Linux下JNA 调用 so 库
- Linux下JNA 调用 so 库
- android 滚轮刻度尺的实现
- J2EE基础知识JSP
- bzoj3810: [Coci2015]Stanovi 记忆化搜索
- ListView连续调用getview问题分析及解决
- 20150712,关于C。
- JNA调用C动态库dll、so
- SpringMVC中servletFileUpload.parseRequest(request)解析为空获取不到数据问题
- hdu 5120
- 指针与数组的区别
- LeetCode题解——Longest Common Prefix
- html5基础视频教程第一节
- 提高Interface Builder高效工作的8个技巧
- C++接口实现总结
- 判断点P是否在三角形ABC内