有没有有效的方法来使用JNA读取动态大小共享内存段?

时间:2015-11-09 09:04:28

标签: java c arrays struct jna

我试图找到以结构数组形式读取共享内存的有效方法(在C中):

typedef struct the_struct {
    int id;
    int data;
} the_c_struct;
static the_c_struct *the_struc_ptr = NULL;

目前,我使用以下JNA Structure代码从共享内存中检索数据:

public class MyCStruc extends Structure {

    public int id;
    public int data;

    @Override
    protected List getFieldOrder() {
        return Arrays.asList(new String[]{"id", "data"});
    }

    @Override
    public void useMemory(Pointer m, int offset) {
        super.useMemory(m, offset);
        super.read();
    }

    @Override
    public void useMemory(Pointer m) {
        super.useMemory(m);
        super.read();
    }

}

使用shmgetshmat的原生实现读取共享内存:

memId = NativeLib.INSTANCE.shmget(0x999, memSize, 0);
CStructPtr = NativeLib.INSTANCE.shmat(memId, null, 0);

MyCStruc cs=new MyCStruc();
for (int i=0;i<CStructArraySize;i+=8) {
    cs.useMemory(CStructPtr,i);
    // to read a record of struct array
    // do something with the data
}

上面的代码实际上是有效的,但我想我可以做一些更有效的方法来读取struct的数组?正确?

注意:struct数组的大小是动态的,但我可以设法获得共享内存的大小。

2 个答案:

答案 0 :(得分:1)

请勿在此处使用Structure,只需让shmat来电回复Pointer,然后使用Pointer.getInt(0)获取ID,Pointer.getInt(4)即可获取data字段。

您甚至可以使用Native.getDirectBufferPointer()为您提供一个可以传递给其他Java代码的NIO缓冲区。

如果您正在阅读连续分配的struct数组,那么您应该使用基于Structure的构造函数创建第一个Pointer,然后在其上调用Structure.toArray(size)实例加载完整数组。

Pointer p = lib.shmat();
MyCStruc s = new MyCStruc(p);
MyCStruc[] array = (MyCStruc[])s.toArray(size);

构造函数:

public class MyCStruc extends Structure {
    public MyCStruc(Pointer p) {
        super(p);
        read();
    }
}

答案 1 :(得分:0)

这是我的最终代码:

memId = NativeLib.INSTANCE.shmget(0x999, memSize, 0);
CStructPtr = NativeLib.INSTANCE.shmat(memId, null, 0);
CStructArraySize=memSize/8;
MyCStruc cs=new MyCStruc(CStructPtr);
MyCStruc[] acs=(MyCStruc[])cs.toArray(CStructArraySize);
int i=0;
while (i<CStructArraySize) {
    System.out.printf("id=%d data=%d\n", acs[i].id, acs[i].data);
    // do something else with the data
    i++;
}

MyCStruc现在:

public class MyCStruc extends Structure {
    public int id;
    public int data;

    @Override
    protected List getFieldOrder() {
        return Arrays.asList(new String[]{"id", "data"});
    }
    public MyCStruc(Pointer p) {
        super(p);
        read();
    }
}