52 lines
2.1 KiB
Java
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);
|
|
}
|
|
}
|
|
}
|