Files
JavaOpenCL64/src/club/doki7/ffm/util/UnixUtil.java
T
2026-08-07 19:33:10 +08:00

52 lines
2.1 KiB
Java

package club.doki7.ffm.util;
import club.doki7.ffm.RawFunctionLoader;
import club.doki7.ffm.library.JavaSystemLibrary;
import org.jetbrains.annotations.Nullable;
import java.lang.foreign.FunctionDescriptor;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.ValueLayout;
import java.lang.invoke.MethodHandle;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
public final class UnixUtil {
/// Force the {@link UnixUtil} class to be loaded, in order to avoid some initialization order
/// issues.
///
/// @implNote The loading of {@link UnixUtil} is done in the static initializer, involving
/// retrieving several function handles. Thus, at the point you call the class methods, if the
/// `UnixUtil` class has not been loaded yet, the loading process may reset the `dlerror` value,
/// which is not what you want. This method is a workaround to force the class to be loaded and
/// initialized, so that the function handles are already retrieved, and the `dlerror` value is
/// not reset.
public static void forceLoad() {}
public static @Nullable String dlerror() {
try {
MethodHandle h = Objects.requireNonNull(hDlerror);
MemorySegment result = (MemorySegment) h.invokeExact();
if (result.equals(MemorySegment.NULL)) {
return null;
}
return result.reinterpret(Long.MAX_VALUE).getString(0, StandardCharsets.UTF_8);
} catch (Throwable e) {
return "dlerror failed to retrieve error message: " + e.getMessage();
}
}
private static final FunctionDescriptor DESCRIPTOR$dlerror =
FunctionDescriptor.of(ValueLayout.ADDRESS.withTargetLayout(ValueLayout.JAVA_BYTE));
private static final @Nullable MethodHandle hDlerror;
static {
MemorySegment pfnDlerror = JavaSystemLibrary.INSTANCE.load("dlerror");
if (pfnDlerror.equals(MemorySegment.NULL)) {
hDlerror = null;
} else {
hDlerror = RawFunctionLoader.link(pfnDlerror, DESCRIPTOR$dlerror);
}
}
}