How to dispatch the same method call on different platforms?
Christoph Läubrich
laeubi at laeubi-soft.de
Sat Feb 17 07:15:20 UTC 2024
It would really great if the JVM (maybe as part of FFM) can offer a way
to get a more semantic wan to query for os/architecture than system
properties with varying names.
Especially as the JVM is a native binary it should know all the details ;-)
In OSGi there is a namespace one can use to filter on [1].
It even defines an Alias list[2], just to give an impression about the
mess one need to handle today with all the different names (what is
maybe even incomplete as of today).
SWT (who has different platforms/arch implementations) has a platform
specific java class that defines a constant with a well known value that
can be used at runtime to find that out [3]
If then jextract would be able to get a list of alternative headers for
different platforms... just dreaming ;-)
best Christoph
[1]
https://docs.osgi.org/specification/osgi.core/8.0.0/framework.namespaces.html#framework.namespaces.osgi.native
[2] https://docs.osgi.org/reference/osnames.html
[3]
https://github.com/eclipse-platform/eclipse.platform.swt/blob/master/bundles/org.eclipse.swt/Eclipse%20SWT%20PI/gtk/org/eclipse/swt/internal/Platform.java
[4]
https://github.com/eclipse-platform/eclipse.platform.swt/blob/master/bundles/org.eclipse.swt/Eclipse%20SWT%20PI/win32/org/eclipse/swt/internal/Platform.java
Am 17.02.24 um 07:53 schrieb tison:
> For example, getpwnam returns passwd struct, but the struct layout is
> various on different platform, making the code snippet below unportable:
>
> final Linker linker = Linker.nativeLinker();
> final SymbolLookup lookup = linker.defaultLookup();
> final MemorySegment getpwnam =
> lookup.find("getpwnam").orElseThrow();
> final MethodHandle getpwnamFn = linker.downcallHandle(getpwnam,
> FunctionDescriptor.of(ValueLayout.ADDRESS, ValueLayout.ADDRESS));
> final StructLayout passwdLayout = MemoryLayout.structLayout(
> ValueLayout.ADDRESS.withName("pw_name"),
> ValueLayout.ADDRESS.withName("pw_passwd"),
> ValueLayout.JAVA_INT.withName("pw_uid"),
> ValueLayout.JAVA_INT.withName("pw_gid"),
> ValueLayout.JAVA_LONG.withName("pw_change"),
> ValueLayout.ADDRESS.withName("pw_class"),
> ValueLayout.ADDRESS.withName("pw_gecos"),
> ValueLayout.ADDRESS.withName("pw_dir"),
> ValueLayout.ADDRESS.withName("pw_shell"),
> ValueLayout.JAVA_LONG.withName("pw_expire"),
> ValueLayout.JAVA_INT.withName("pw_fields"));
> try (final Arena arena = Arena.ofConfined()) {
> final MemorySegment username = arena.allocateUtf8String(user);
> final MemorySegment passwd = ((MemorySegment)
> getpwnamFn.invoke(username)).reinterpret(Long.MAX_VALUE);
> final MemorySegment dir = passwd.get(
> ValueLayout.ADDRESS,
>
> passwdLayout.byteOffset(MemoryLayout.PathElement.groupElement("pw_dir")));
>
> System.out.println(dir.reinterpret(Long.MAX_VALUE).getUtf8String(0));
> }
>
> This code snippet only works on macOS because the layout differs on
> other platforms.
>
> In Rust, we can use #[target(os = ..)] to switch the manner, and in
> Java, perhaps we can use inheritance or interfaces, but it still lacks:
>
> * A unified way to determine current os, arch, toolchain, etc. I made
> [1] that can help but it's no more than another incomplete slang.
> * A compile-time dispatch decision. Maybe with static initialization
> block it can helps by generating 'static final'
> MethodHandle/VarHandle. I don't know.
>
> Best,
> tison.
>
> [1] github.com/tisonspieces/os-detector
> <http://github.com/tisonspieces/os-detector>
>
More information about the panama-dev
mailing list