Skip to content

Instantly share code, notes, and snippets.

@Glavo
Created May 14, 2023 11:35
Show Gist options
  • Save Glavo/8e5f58099c8faa4672f8b31f4557bf6d to your computer and use it in GitHub Desktop.
Save Glavo/8e5f58099c8faa4672f8b31f4557bf6d to your computer and use it in GitHub Desktop.
import java.lang.foreign.*;
import java.lang.invoke.*;
import java.util.Arrays;
import static java.lang.foreign.ValueLayout.*;
public class Test {
@FunctionalInterface
public interface Callback {
int invoke(MemorySegment a, MemorySegment b);
}
private static final MethodHandle callbackMethodHandle;
private static final MethodHandle qsortHandle;
static {
try {
callbackMethodHandle = MethodHandles.publicLookup()
.findVirtual(Callback.class, "invoke", MethodType.methodType(int.class, MemorySegment.class, MemorySegment.class));
qsortHandle = Linker.nativeLinker().downcallHandle(
Linker.nativeLinker().defaultLookup().find("qsort").get(),
FunctionDescriptor.ofVoid(ADDRESS, JAVA_LONG, JAVA_LONG, ADDRESS)
);
} catch (NoSuchMethodException | IllegalAccessException e) {
throw new InternalError(e);
}
}
public static void qsort(MemorySegment array, Callback callback) {
try (var arena = Arena.ofConfined()) {
MemorySegment comparator = Linker.nativeLinker().upcallStub(
callbackMethodHandle.bindTo(callback),
FunctionDescriptor.of(JAVA_INT, ADDRESS.withTargetLayout(JAVA_INT), ADDRESS.withTargetLayout(JAVA_INT)),
arena);
qsortHandle.invokeExact(
array,
(long) (array.byteSize() / Integer.BYTES),
(long) Integer.BYTES,
comparator);
} catch (Throwable e) {
throw new InternalError(e);
}
}
public static void main(String[] args) throws Exception {
try (var arena = Arena.ofConfined()) {
var array = arena.allocateArray(JAVA_INT, 0, 9, 3, 4, 6, 5, 1, 8, 2, 7);
qsort(array, (a, b) -> Integer.compare(a.get(JAVA_INT, 0), b.get(JAVA_INT, 0)));
System.out.println(Arrays.toString(array.toArray(JAVA_INT)));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment