Как получить доступ к C_POINTER в MemoryLayout с помощью Java Panama FFI

Используя предварительный просмотр FFI в JDK 16, у меня есть такой макет памяти:

      class FfiTest {
    static GroupLayout layout = MemoryLayout.ofStruct(
        C_INT.withName("someInt"),
        MemoryLayout.ofPaddingBits(32), // So the following pointer is aligned at 64 bits
        C_POINTER.withName("somePtr")
    );
}

Затем я получаю указатель на такую ​​структуру в обратном вызове из собственного кода:

      public static void someCallback(MemoryAddress address) {
    try (MemorySegment seg = address.asSegmentRestricted(FfiTest.layout.byteSize())) {                

        // Works: fetching int from native structure, correct value is returned
        VarHandle intHandle = FfiTest.layout.varHandle(int.class, MemoryLayout.PathElement.groupElement("someInt"));
        int intResult = (int) vh.get(seg);

        // Does not work: get the pointer as a MemoryAddress, fatal JVM crash with Hotspot log
        VarHandle badPtrHandle = FfiTest.layout.varHandle(MemoryAddress.class, MemoryLayout.PathElement.groupElement("somePtr"));

        // Works: get the pointer as a long, correct value is returned
        VarHandle goodPtrHandle = FfiTest.layout.varHandle(long.class, MemoryLayout.PathElement.groupElement("somePtr"));
        long longResult = (long) goodPtrHandle.get(seg);
    }
}

Исключение возникает внутри кода JDK в jdk.internal.foreign.Utils:

          public static void checkPrimitiveCarrierCompat(Class<?> carrier, MemoryLayout layout) {
        checkLayoutType(layout, ValueLayout.class);
        if (!isValidPrimitiveCarrier(carrier))
            throw new IllegalArgumentException("Unsupported carrier: " + carrier); // Throws this exception, carrier has the value MemoryAddress
        if (Wrapper.forPrimitiveType(carrier).bitWidth() != layout.bitSize())
            throw new IllegalArgumentException("Carrier size mismatch: " + carrier + " != " + layout);
    }

Согласно документации Панамы, носитель Java для C_POINTER должен быть MemoryAddress, но здесь это не работает.

Так правильно ли использовать longs для доступа к таким указателям? Или что-то другое?

1 ответ

Решение

Как отмечает Йоханнес в комментариях, <tcode id="21622471"></tcode> можно использовать для адаптации long ручку вы должны принять и вернуть MemoryAddress:

      VarHandle goodPtrHandle = FfiTest.layout.varHandle(long.class, MemoryLayout.PathElement.groupElement("somePtr"));
long longResult = (long) goodPtrHandle.get(seg);
VarHandle addrHandle = MemoryHandles.asAddressVarHandle(goodPtrHandle);
MemoryAddress addrResult = (MemoryAddress) addrHandle.get(seg);
Другие вопросы по тегам