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:

扫描二维码关注公众号,回复: 6269730 查看本文章

关键方法: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退出。

猜你喜欢

转载自www.cnblogs.com/andyhe/p/10918822.html
jna