graal conf

This commit is contained in:
Gregor Lohaus
2026-05-27 14:11:20 +02:00
parent be0c0bb321
commit a03bc2ec48
4 changed files with 176 additions and 24 deletions

View File

@@ -4,6 +4,7 @@ import dev.jlibghostty.GhosttyException;
import dev.jlibghostty.TerminalOptions;
import java.lang.foreign.Arena;
import java.lang.foreign.AddressLayout;
import java.lang.foreign.FunctionDescriptor;
import java.lang.foreign.GroupLayout;
import java.lang.foreign.Linker;
@@ -15,11 +16,7 @@ import java.lang.invoke.MethodHandle;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import static java.lang.foreign.ValueLayout.ADDRESS;
import static java.lang.foreign.ValueLayout.JAVA_BOOLEAN;
import static java.lang.foreign.ValueLayout.JAVA_BYTE;
import static java.lang.foreign.ValueLayout.JAVA_INT;
import static java.lang.foreign.ValueLayout.JAVA_SHORT;
public final class GhosttyLibrary {
public static final int TERMINAL_DATA_COLS = 1;
@@ -35,17 +32,21 @@ public final class GhosttyLibrary {
private static final int GHOSTTY_NO_VALUE = -4;
private static final Linker LINKER = Linker.nativeLinker();
private static final AddressLayout C_POINTER = (AddressLayout) LINKER.canonicalLayouts().get("void*");
private static final ValueLayout.OfBoolean C_BOOL = (ValueLayout.OfBoolean) LINKER.canonicalLayouts().get("bool");
private static final ValueLayout.OfShort C_SHORT = (ValueLayout.OfShort) LINKER.canonicalLayouts().get("short");
private static final ValueLayout.OfInt C_INT = (ValueLayout.OfInt) LINKER.canonicalLayouts().get("int");
private static final ValueLayout.OfLong C_SIZE_T = sizeTLayout();
private static final GroupLayout TERMINAL_OPTIONS = MemoryLayout.structLayout(
JAVA_SHORT.withName("cols"),
JAVA_SHORT.withName("rows"),
C_SHORT.withName("cols"),
C_SHORT.withName("rows"),
MemoryLayout.paddingLayout(4),
C_SIZE_T.withName("max_scrollback")
);
private static final GroupLayout GHOSTTY_STRING = MemoryLayout.structLayout(
ADDRESS.withName("ptr"),
C_POINTER.withName("ptr"),
C_SIZE_T.withName("len")
);
@@ -63,21 +64,21 @@ public final class GhosttyLibrary {
SymbolLookup symbols = SymbolLookup.libraryLookup(libraryPath, Arena.global());
terminalNew = downcall(symbols, "ghostty_terminal_new",
FunctionDescriptor.of(JAVA_INT, ADDRESS, ADDRESS, TERMINAL_OPTIONS));
FunctionDescriptor.of(C_INT, C_POINTER, C_POINTER, TERMINAL_OPTIONS));
terminalFree = downcall(symbols, "ghostty_terminal_free",
FunctionDescriptor.ofVoid(ADDRESS));
FunctionDescriptor.ofVoid(C_POINTER));
terminalReset = downcall(symbols, "ghostty_terminal_reset",
FunctionDescriptor.ofVoid(ADDRESS));
FunctionDescriptor.ofVoid(C_POINTER));
terminalResize = downcall(symbols, "ghostty_terminal_resize",
FunctionDescriptor.of(JAVA_INT, ADDRESS, JAVA_SHORT, JAVA_SHORT, JAVA_INT, JAVA_INT));
FunctionDescriptor.of(C_INT, C_POINTER, C_SHORT, C_SHORT, C_INT, C_INT));
terminalVtWrite = downcall(symbols, "ghostty_terminal_vt_write",
FunctionDescriptor.ofVoid(ADDRESS, ADDRESS, C_SIZE_T));
FunctionDescriptor.ofVoid(C_POINTER, C_POINTER, C_SIZE_T));
terminalGet = downcall(symbols, "ghostty_terminal_get",
FunctionDescriptor.of(JAVA_INT, ADDRESS, JAVA_INT, ADDRESS));
FunctionDescriptor.of(C_INT, C_POINTER, C_INT, C_POINTER));
pasteIsSafe = downcall(symbols, "ghostty_paste_is_safe",
FunctionDescriptor.of(JAVA_BOOLEAN, ADDRESS, C_SIZE_T));
FunctionDescriptor.of(C_BOOL, C_POINTER, C_SIZE_T));
pasteEncode = downcall(symbols, "ghostty_paste_encode",
FunctionDescriptor.of(JAVA_INT, ADDRESS, C_SIZE_T, JAVA_BOOLEAN, ADDRESS, C_SIZE_T, ADDRESS));
FunctionDescriptor.of(C_INT, C_POINTER, C_SIZE_T, C_BOOL, C_POINTER, C_SIZE_T, C_POINTER));
} catch (IllegalCallerException e) {
throw new IllegalStateException(
"FFM native access is disabled. Run with --enable-native-access=dev.jlibghostty "
@@ -93,17 +94,17 @@ public final class GhosttyLibrary {
public MemorySegment terminalNew(TerminalOptions options) {
try (Arena arena = Arena.ofConfined()) {
MemorySegment out = arena.allocate(ADDRESS);
MemorySegment out = arena.allocate(C_POINTER);
MemorySegment nativeOptions = arena.allocate(TERMINAL_OPTIONS);
nativeOptions.set(JAVA_SHORT, 0, (short) options.columns());
nativeOptions.set(JAVA_SHORT, 2, (short) options.rows());
nativeOptions.set(C_SHORT, 0, (short) options.columns());
nativeOptions.set(C_SHORT, 2, (short) options.rows());
nativeOptions.set(C_SIZE_T, 8, options.maxScrollback());
int result = (int) terminalNew.invoke(MemorySegment.NULL, out, nativeOptions);
checkResult("ghostty_terminal_new", result);
MemorySegment terminal = out.get(ADDRESS, 0);
MemorySegment terminal = out.get(C_POINTER, 0);
if (terminal.address() == 0) {
throw new IllegalStateException("ghostty_terminal_new returned a null terminal handle");
}
@@ -160,10 +161,10 @@ public final class GhosttyLibrary {
public int terminalGetU16(MemorySegment terminal, int key) {
try (Arena arena = Arena.ofConfined()) {
MemorySegment out = arena.allocate(JAVA_SHORT);
MemorySegment out = arena.allocate(C_SHORT);
int result = (int) terminalGet.invoke(terminal, key, out);
checkResult("ghostty_terminal_get", result);
return Short.toUnsignedInt(out.get(JAVA_SHORT, 0));
return Short.toUnsignedInt(out.get(C_SHORT, 0));
} catch (Throwable t) {
return rethrow(t);
}
@@ -171,10 +172,10 @@ public final class GhosttyLibrary {
public boolean terminalGetBoolean(MemorySegment terminal, int key) {
try (Arena arena = Arena.ofConfined()) {
MemorySegment out = arena.allocate(JAVA_BOOLEAN);
MemorySegment out = arena.allocate(C_BOOL);
int result = (int) terminalGet.invoke(terminal, key, out);
checkResult("ghostty_terminal_get", result);
return out.get(JAVA_BOOLEAN, 0);
return out.get(C_BOOL, 0);
} catch (Throwable t) {
return rethrow(t);
}
@@ -189,7 +190,7 @@ public final class GhosttyLibrary {
}
checkResult("ghostty_terminal_get", result);
MemorySegment ptr = out.get(ADDRESS, 0);
MemorySegment ptr = out.get(C_POINTER, 0);
long len = out.get(C_SIZE_T, 8);
if (ptr.address() == 0 || len == 0) {
return "";