JNA 相关问题
JNA 相关问题
结构体对齐问题
要注意调用的c库字段对齐方式的相关设置。
#pragma pack (push,1)
#pragma pack(pop)
jna中提供了4种对齐方式:
/** Use the platform default alignment. */
public static final int ALIGN_DEFAULT = 0;
/** No alignment, place all fields on nearest 1-byte boundary */
public static final int ALIGN_NONE = 1;
/** validated for 32-bit x86 linux/gcc; align field size, max 4 bytes */
public static final int ALIGN_GNUC = 2;
/** validated for w32/msvc; align on field size */
public static final int ALIGN_MSVC = 3;
需要在相应的结构体构造函数中加入super(ALIGN_NONE);设置对应的对齐方式。
unsigned类型处理
java中没有对应的无符号类型,需要进行相应的转换,以byte类型为例(c中的 unsigned char)
public class Util {
public static byte sendUnsignedByte(int input){
return (byte) (input & 0xFF);
}
public static int receiveUnsignedByte(byte input){
return input & 0xFF;
}
}
char*
const char* 作为函数参数,可以直接用字符串String传值。
char** 函数回传字符串。用PointerByReference
char** 发送数据到struct的char**类型的字段中:new StringArray(String[] strings);
获取struct中的char**类型回传的数据: String[] getStringArray(long offset, int length)
final PointerByReference ptrRef = new PointerByReference();
final Pointer p = ptrRef.getValue();
final String val = p.getString(0);
获取数据,内存由c分配,那么需要c同时提供jni接口释放获取到的内存。
发送数据:
String strInfo = "very nice";
byte[] bInfo = strInfo.getBytes();
Memory info = new Memory(bInfo.length + 1);
info.clear();
info.write(0,bInfo,0,bInfo.length);
info.setByte(bInfo.length,(byte)0);
p.info = info;
struct 数组
获取数据,要调用c的接口释放分配的内存
传递数组到c:
关键方法:public Structure[] toArray(int size)用于在java中分配内存,和把c中获取的内存空间转化为Structure数组.
callback
typedef void(*callback)(PERSON*);
public static class ShowCallBack implements Callback{
public void invoke(Person.ByReference person){
String name = "";
byte[] data = person.name;
int count = data.length;
for(int i=data.length - 1;i>= 0;i--){
if(data[i] != 0) {
break;
}
count--;
}
if(count > 0) {
byte[] copy = new byte[count];
System.arraycopy(data,0,copy,0,count);
name = new String(copy);
}
System.out.println("callback name\t"+name);
}
}
用byte[]数组值给char[]
由于c中字符串以\0结尾,因此需要在末尾多分配一个字节的空间,并把这个末尾字节设置为0
byte[] bInfo = strInfo.getBytes();
Memory info = new Memory(bInfo.length + 1);
info.write(0,bInfo,0,bInfo.length);
info.setByte(bInfo.length,(byte)0);
jvm异常退出
JNA也提供了一种保护机制。比如防止JNA出现异常不会导致JVM异常退出,默认是开启这个功能的,开启方式为 System.setProperty("jna.protected","true"); 记得要在JNA加载库文件之前调用,然后try {...} catch(Throwable e)异常,出现”非法内存访问”的时候依然会导致jvm退出。
函数调用约定
_stdcall和_cdecl函数调用约定 参考链接
_cdecl,是C语言缺省的调用约定,参数采用从右到左的压栈方式,函数本身不清理堆栈,调用者负责清理堆栈。对于这种库,只要直接继承Library。
_stdcall,是Pascal程序的缺省调用方式,WIN32 Api都采用_stdcall调用方式。参数采用从右到左的压栈方式,被调函数自身在返回前清空堆栈。这种需要继承StdCallLibrary。
如果用cpp实现库,需要调用的函数申明添加extern "C"
#pragma pack(push,1) //紧凑型对齐
#ifdef __cplusplus
extern "C" {
#endif
typedef void(*callback)(PERSON*);
void show(PERSON* person,const callback cb);
// ...更多的方法
#ifdef __cplusplus
}
#endif
#pragma pack(pop)
柔性数组成员(flexible array member)
struct blob {
size_t length;
unsigned char data[];
};
class Blob extends Structure {
int length;
byte[] data = new byte[1];
public blob(int length) {
this.length = length;
this.data = new byte[length];
allocateMemory();
}
public blob(Pointer p) {
super(p);
this.length = p.readInt(0);
this.data = new byte[this.length];
read();
}
}
Strucure内存大小在java中有改动后需要及时调用allocateMemory()重新分配内存. write()方法把Strucure对象的改动及时写入到本地内存中,read()重新把本地内存中的数据读取到Strucure对象。
参考文件
JNA 相关问题的更多相关文章
- JNI与JNA性能比较
JNI与JNA性能比较 在介绍JNA时,提到了JNA是基于JNI的,是在JNI上封装了一层,JNI性能不如JNA.最近在网上看到篇简单的比较这两者性能的文档,感觉不错,现转载一下: 分别用JNI和JN ...
- 嵌入式单片机STM32应用技术(课本)
目录SAIU R20 1 6 第1页第1 章. 初识STM32..................................................................... ...
- JNA入门实例
JNA(Java Native Access):建立在JNI之上的Java开源框架,SUN主导开发,用来调用C.C++代码,尤其是底层库文件(windows中叫dll文件,linux下是so[shar ...
- JNI的替代者—使用JNA访问Java外部功能接口
摘自:http://www.cnblogs.com/lanxuezaipiao/p/3635556.html JNI的替代者-使用JNA访问Java外部功能接口 1. JNA简单介绍 先说JNI(Ja ...
- Java(使用JNA)调用DLL库与C#调用DLL库的对比
前言:在项目中经常使用DLL库对硬件进行操作,在发卡过程中使用频率尤为多,今天就Java与C#中调用DLL库的使用区别做一个介绍,本文着重具体的代码编写,具体过程看以下代码. 前提条件: 笔者已经封装 ...
- Java跨语言调用,使用JNA访问Java外部接口
1. JNA简单介绍 先说JNI(Java Native Interface)吧,有过不同语言间通信经历的一般都知道,它允许Java代码和其他语言(尤其C/C++)写的代码进行交互,只要遵守调用约定即 ...
- Atitit. 。Jna技术与 解决 java.lang.Error: Invalid memory access
Atitit. .Jna技术与 解决 java.lang.Error: Invalid memory access 1. 原因与解决1 2. jNA (这个ms sun 的)1 3. Code1 4. ...
- java使用JNA框架调用dll动态库
这两天了解了一下java调用dll动态库的方法,总的有三种:JNI.JNA.JNative.其中JNA调用DLL是最方便的. ·JNI ·JNA ·JNative java使用 JNI来调用dll动态 ...
- Awesome Java: Github上关于Java相关的工具
Awesome Java 这是Github上关于Java相关的工具,框架等等资源集合. 原文参考: https://github.com/akullpp/awesome-java. @pdai 最全的 ...
随机推荐
- 用Python抓取并分析了1982场英雄联盟数据,教你开局前预测游戏对局胜负!
英雄联盟想必大多数读者不会陌生,这是一款来自拳头,由腾讯代理的大型网络游戏,现在一进网吧,你就能发现一大片玩英雄联盟的人.在2017年中国战队无缘鸟巢的世界总决赛后,一大片人选择了弃游,只是终究没躲过 ...
- poj 2718 切数问题 穷竭搜索
题意: 给一个已经排序号的数字,从中间切一刀,成两个数,要求这两个数的差最小 思路:暴力比较差最小值 stl中的next_permutation()函数进行排列 注意:这个函数必须从小到大才可以排序 ...
- [转] Vuex入门(2)—— state,mapState,...mapState对象展开符详解
1.state state是什么? 定义:state(vuex) ≍ data (vue) vuex的state和vue的data有很多相似之处,都是用于存储一些数据,或者说状态值.这些值都将被挂载 ...
- day18-socket 编程
1.Socket是网络上的使用的交互信息得方法,也叫套接字 用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. 通讯原理 Soc ...
- Python 基础(一)
本章内容 1.编译和解释型语言的区别 2.Python的解释器 3.pyc文件 4.运行环境 5.变量 6.数据类型 7.字符编码 8.三元运算 编译和解释型语言的区别 编译器是把源程序的每一条语句都 ...
- RHEL6.X设置163yum源
目录 RHEL6.X设置163yum源 卸载系统的yum 检查是否已经卸载完成 下载yum以及相关包 安装yum相关rpm包 清除原有缓存,建立yum列表 本地yum源设置 挂载本地光盘 修改配置文件 ...
- 程序员必需知道的windows快捷键
系统操作的快捷键 1.F5------刷新 2.window+E------打开我的电脑 3.window+r------打开运行 4.window+l------快速锁机 5.window+d--- ...
- 理解依赖注入 for Zend framework 2
依赖注入(Dependency Injection),也成为控制反转(Inversion of Control),一种设计模式,其目的是解除类之间的依赖关系. 假设我们需要举办一个Party,Part ...
- python算法-汉诺塔问题
汉诺塔问题 初始状态: 思考:当盘子的个数是3的时候,大家写出移动顺序 移动的步骤: 3个盘子,从a到c 1.前面两个盘子,从a到b 1)把前面一个盘子,从a到c a->c 2)把第二个盘子 ...
- 【瓜分5000元奖金】Wannafly挑战赛13
链接:https://www.nowcoder.com/acm/contest/80/A来源:牛客网 zzy的小号 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他 ...