有什么有效的方法可以使用 JNA 读取动态大小的共享内存段吗?

Is there any effective way to read dynamic size shared memory segment using 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
}

上面的代码确实有效,但我想我可以做一些更有效的事情来读取结构数组?对吗?

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

不要在这里使用 Structure,只需让 shmat 调用 return 一个 Pointer 并使用 Pointer.getInt(0) 获取 ID 和Pointer.getInt(4) 获取 data 字段。

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

如果您正在读取连续分配的数组 struct,那么您应该使用基于 Pointer 的构造函数创建您的第一个 Structure,然后调用 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();
    }
}

这是我的最终代码:

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();
    }
}