我想通过FFI/巴拿马从Java访问PKCS11图书馆.假设我们在Windows x64下有以下打包的组布局:
GroupLayout groupLayout = MemoryLayout.structLayout(
MemoryLayout.sequenceLayout(64, JAVA_BYTE).withName("slotDescription"),
MemoryLayout.sequenceLayout(32, JAVA_BYTE).withName("manufacturerId"),
JAVA_INT_UNALIGNED.withName("flags"),
MemoryLayout.structLayout(
JAVA_BYTE.withName("major"),
JAVA_BYTE.withName("minor")
).withName("hardwareVersion"),
MemoryLayout.structLayout(
JAVA_BYTE.withName("major"),
JAVA_BYTE.withName("minor")
).withName("firmwareVersion")
).withName("CK_SLOT_INFO");
一个简单的方法是写一个helper方法:
public static String getString(MemorySegment memorySegment, int offset, int length) {
byte[] slicedData = new byte[length];
MemorySegment slicedMemorySegment = memorySegment.asSlice(offset, length);
slicedMemorySegment.asByteBuffer().get(slicedData);
return new String(slicedData);
}
然后使用偏移量和长度调用它:
String manufacturerId = MemorySegmentUtils.getString(memorySegment, 64, 32);
因为PKCS11使用不同的填充/填充,所以我不想硬编码这些偏移量和长度.像在Java VarHandle to a C string with java.lang.foreign API中提到的那样使用getUtf8String
是不起作用的,因为字符字符串是固定的,并且不是以零结尾.
那么,我如何使用MethodHandle
来读取这些字节:
MethodHandle methodHandle = groupLayout.sliceHandle(MemoryLayout.PathElement.groupElement("manufacturerId"));
// What to do now?
String manufacturerId = ???