JNA 相关问题

结构体对齐问题

要注意调用的c库字段对齐方式的相关设置。

  1. #pragma pack (push,1)
  2. #pragma pack(pop)

jna中提供了4种对齐方式:

  1. /** Use the platform default alignment. */
  2. public static final int ALIGN_DEFAULT = 0;
  3. /** No alignment, place all fields on nearest 1-byte boundary */
  4. public static final int ALIGN_NONE = 1;
  5. /** validated for 32-bit x86 linux/gcc; align field size, max 4 bytes */
  6. public static final int ALIGN_GNUC = 2;
  7. /** validated for w32/msvc; align on field size */
  8. public static final int ALIGN_MSVC = 3;

需要在相应的结构体构造函数中加入super(ALIGN_NONE);设置对应的对齐方式。

unsigned类型处理

java中没有对应的无符号类型,需要进行相应的转换,以byte类型为例(c中的 unsigned char)

  1. public class Util {
  2. public static byte sendUnsignedByte(int input){
  3. return (byte) (input & 0xFF);
  4. }
  5. public static int receiveUnsignedByte(byte input){
  6. return input & 0xFF;
  7. }
  8. }

char*

const char* 作为函数参数,可以直接用字符串String传值。

char** 函数回传字符串。用PointerByReference

char** 发送数据到struct的char**类型的字段中:new StringArray(String[] strings);

获取struct中的char**类型回传的数据: String[] getStringArray(long offset, int length)

  1. final PointerByReference ptrRef = new PointerByReference();
  2. final Pointer p = ptrRef.getValue();
  3. final String val = p.getString(0);

获取数据,内存由c分配,那么需要c同时提供jni接口释放获取到的内存。

发送数据:

  1. String strInfo = "very nice";
  2. byte[] bInfo = strInfo.getBytes();
  3. Memory info = new Memory(bInfo.length + 1);
  4. info.clear();
  5. info.write(0,bInfo,0,bInfo.length);
  6. info.setByte(bInfo.length,(byte)0);
  7. p.info = info;

struct 数组

获取数据,要调用c的接口释放分配的内存

传递数组到c:

关键方法:public Structure[] toArray(int size)用于在java中分配内存,和把c中获取的内存空间转化为Structure数组.

callback

  1. typedef void(*callback)(PERSON*);
  1. public static class ShowCallBack implements Callback{
  2. public void invoke(Person.ByReference person){
  3. String name = "";
  4. byte[] data = person.name;
  5. int count = data.length;
  6. for(int i=data.length - 1;i>= 0;i--){
  7. if(data[i] != 0) {
  8. break;
  9. }
  10. count--;
  11. }
  12. if(count > 0) {
  13. byte[] copy = new byte[count];
  14. System.arraycopy(data,0,copy,0,count);
  15. name = new String(copy);
  16. }
  17. System.out.println("callback name\t"+name);
  18. }
  19. }

用byte[]数组值给char[]

由于c中字符串以\0结尾,因此需要在末尾多分配一个字节的空间,并把这个末尾字节设置为0

  1. byte[] bInfo = strInfo.getBytes();
  2. Memory info = new Memory(bInfo.length + 1);
  3. info.write(0,bInfo,0,bInfo.length);
  4. 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"

  1. #pragma pack(push,1) //紧凑型对齐
  2. #ifdef __cplusplus
  3. extern "C" {
  4. #endif
  5. typedef void(*callback)(PERSON*);
  6. void show(PERSON* person,const callback cb);
  7. // ...更多的方法
  8. #ifdef __cplusplus
  9. }
  10. #endif
  11. #pragma pack(pop)

柔性数组成员(flexible array member)

  1. struct blob {
  2. size_t length;
  3. unsigned char data[];
  4. };
  1. class Blob extends Structure {
  2. int length;
  3. byte[] data = new byte[1];
  4. public blob(int length) {
  5. this.length = length;
  6. this.data = new byte[length];
  7. allocateMemory();
  8. }
  9. public blob(Pointer p) {
  10. super(p);
  11. this.length = p.readInt(0);
  12. this.data = new byte[this.length];
  13. read();
  14. }
  15. }

Strucure内存大小在java中有改动后需要及时调用allocateMemory()重新分配内存. write()方法把Strucure对象的改动及时写入到本地内存中,read()重新把本地内存中的数据读取到Strucure对象。

参考文件

官方文档

用例文档

JNA 相关问题的更多相关文章

  1. JNI与JNA性能比较

    JNI与JNA性能比较 在介绍JNA时,提到了JNA是基于JNI的,是在JNI上封装了一层,JNI性能不如JNA.最近在网上看到篇简单的比较这两者性能的文档,感觉不错,现转载一下: 分别用JNI和JN ...

  2. 嵌入式单片机STM32应用技术(课本)

    目录SAIU R20 1 6 第1页第1 章. 初识STM32..................................................................... ...

  3. JNA入门实例

    JNA(Java Native Access):建立在JNI之上的Java开源框架,SUN主导开发,用来调用C.C++代码,尤其是底层库文件(windows中叫dll文件,linux下是so[shar ...

  4. JNI的替代者—使用JNA访问Java外部功能接口

    摘自:http://www.cnblogs.com/lanxuezaipiao/p/3635556.html JNI的替代者-使用JNA访问Java外部功能接口 1. JNA简单介绍 先说JNI(Ja ...

  5. Java(使用JNA)调用DLL库与C#调用DLL库的对比

    前言:在项目中经常使用DLL库对硬件进行操作,在发卡过程中使用频率尤为多,今天就Java与C#中调用DLL库的使用区别做一个介绍,本文着重具体的代码编写,具体过程看以下代码. 前提条件: 笔者已经封装 ...

  6. Java跨语言调用,使用JNA访问Java外部接口

    1. JNA简单介绍 先说JNI(Java Native Interface)吧,有过不同语言间通信经历的一般都知道,它允许Java代码和其他语言(尤其C/C++)写的代码进行交互,只要遵守调用约定即 ...

  7. 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. ...

  8. java使用JNA框架调用dll动态库

    这两天了解了一下java调用dll动态库的方法,总的有三种:JNI.JNA.JNative.其中JNA调用DLL是最方便的. ·JNI ·JNA ·JNative java使用 JNI来调用dll动态 ...

  9. Awesome Java: Github上关于Java相关的工具

    Awesome Java 这是Github上关于Java相关的工具,框架等等资源集合. 原文参考: https://github.com/akullpp/awesome-java. @pdai 最全的 ...

随机推荐

  1. NXP低功耗蓝牙集成芯片QN9080C的时钟配置

    /*************************************************************************************************** ...

  2. WZK的减肥计划

    WZK 的减肥计划(plan.cpp/ plan.in/ plan.out)问题描述:WZK 发现他的体重正迅猛的上升着,对此他感到非常焦虑,想要制定出一套完美的减肥计划. 于是 WZK 翻阅资料,查 ...

  3. jmeter jdbc各字段的含义

    JDBC采样器各选项的含义如下: 1.Variable Name 其中的Variable Name和上面JDBC Connection Configuration中的Variable Name相同,这 ...

  4. goalng导出excel(csv格式)

    最近项目中有个小需求,需要将查询结果导出到excel.之间前java比较容易,使用POI很容易就能实现,查了下golang的文档,发现golang下边并没有导出excel的包,但是却有一个encodi ...

  5. 2049: [Sdoi2008]Cave 洞穴勘测(LCT)

    2049: [Sdoi2008]Cave 洞穴勘测 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 9962  Solved: 4824[Submit] ...

  6. 全链路spring cloud sleuth+zipkin

    http://blog.csdn.net/qq_15138455/article/details/72956232 版权声明:@入江之鲸 一.About ZipKin please google 二. ...

  7. webdriver高级应用- 高亮显示正在操作的页面元素

    #encoding=utf-8 import unittest from selenium import webdriver import time def highLightElement(driv ...

  8. 《Nginx高性能Web服务器详解》

    第1章 Nginx初探 第2章 Nginx服务器的安装部署 第3章 Nginx服务器架构初探 第4章 Nginx服务器的高级设置 第5章 Nginx服务器的Gzip压缩 第6章 Nginx服务器的Re ...

  9. [python][oldboy] * **的用法

    * 和**主要用在函数的参数中, # coding=utf8 """ 三种编码: 1 python程序代码的编码 # coding=utf8 2 设置/查看python程 ...

  10. VMware 11 安装Mac 10.9

    VMware Workstation 11, 10, 9 and 8 Unlocker to Run Mac OS X Guests in Windows 8.1 and 7 VM10装Mac OS ...