我从第一原理开始使用 FFM 来访问本机结构,例如:
VkLayerProperties {
char layerName[256];
uint32_t specVersion;
uint32_t implementationVersion;
char description[256];
};
以下简单代码从给定的堆外内存地址中提取字段:
public void load(MemorySegment address) {
var layout = MemoryLayout.structLayout(
MemoryLayout.sequenceLayout(256, JAVA_BYTE).withName("layerName"),
JAVA_INT.withName("specVersion"),
JAVA_INT.withName("implementationVersion"),
MemoryLayout.sequenceLayout(256, JAVA_BYTE).withName("description")
);
VarHandle handle = layout.varHandle(PathElement.groupElement("specVersion"));
int specVersion = (int) handle.get(address, 0L);
....
}
这对于原始字段(以及引用类型)效果很好。 但是如何使用布局和路径元素的相同模式来创建两个 array 字段的 var 句柄呢? 我已经尝试了各种元素类的每种组合,尝试了
MethodHandles
中的帮助器等等,但都没有任何运气。
要么句柄因“不是值布局”错误而失败,要么
get
失败(大概)因为坐标错误。 我怀疑我只是比平常更愚蠢。
但是,如果查看使用
jextract
为该结构生成的等效代码,你会发现,它本质上只是硬编码了字节偏移量:
public class VkLayerProperties {
public static MemorySegment layerName$slice(MemorySegment seg) {
return seg.asSlice(0, 256);
}
}
所有非数组字段都按预期使用句柄:
static final VarHandle const$1 = constants$53.const$0.varHandle(MemoryLayout.PathElement.groupElement("specVersion"));
public static int specVersion$get(MemorySegment seg) {
return (int)constants$53.const$1.get(seg);
}
显然,我可以使用相同的方法并根据布局计算字节偏移量和大小(甚至只是对它们进行硬编码),但似乎使用路径元素框架是首选解决方案。
所以:
有没有办法通过从结构内存布局派生 var 句柄来访问 array 字段?
为什么等效的
jextract
绕过一般方法并在这些情况下使用内存切片。
这两个问题有联系吗?
请注意,“使用 jextract”不是答案。
预先感谢您的任何建议或解决方案。