How to dispatch the same method call on different platforms?

tison wander4096 at gmail.com
Sat Feb 17 06:53:07 UTC 2024


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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/panama-dev/attachments/20240217/8bff237f/attachment.htm>


More information about the panama-dev mailing list