Anyone know how I might check if an API is availab...
# kotlin-native
m
Anyone know how I might check if an API is available, and then call that function? Linux glibc 2.29+ supports the following function
posix_spawn_file_actions_addchdir_fp
, but because kotlin compiles against glibc <
2.29
, it is not available from Kotlin. I would like to call it if the
gnu_get_libc_version
returns
2.29
or greater, instead of having to fall back to doing fork/exec. As far as I am aware,
syscall
cannot be used to call this function, so. Any thoughts?
If I add it as an
external fun
in
linuxMain
source set, would that cause issues for people running this whereby the function is not available? What if it is never called (because I check if
glibc
is >
2.28
before hand), would the
external fun
cause issue?
Is there any way to express a
weak
reference, like in rust? This stackoverflow answer suggests to use a weak reference to it, and in fact that is what I am seeing in the Rust lib that I am looking at. https://stackoverflow.com/questions/8814705/how-to-check-if-a-function-exists-in-c-c/43854514#43854514
e
dlsym should work in Kotlin/Native
m
Could I hold onto that OpaquePointer statically, or do I have to release it and perform
dlsym
every time the function is invoked? e.g.
Copy code
// Example.kt

package io.matthewnelson.kmp.process.internal

internal val P_SPAWN_ADDCHDIR_NP by lazy {
    val ptr = dlsym(null, "posix_spawn_file_actions_addchdir_np")
    if (ptr == null) return@lazy null
    CFunction<(actions: CValuesRef<posix_spawn_file_actions_t>, path: String) -> Int>(ptr.rawValue)
}
e
you can hold onto it until the library is unloaded (and since it's libc it won't be unloaded)
❤️ 1
m
We're close, but any ideas on how to pass a
kotlin.String
as a function parameter? Keep getting the following error Error is
type kotlin.string? is not supported here: doesn't correspond to any C type
Figured it out... a little unsafe cast and we good
Copy code
private val ADDCHDIR_NP by lazy {
    val ptr = dlsym(null, "posix_spawn_file_actions_addchdir_np")
        ?: return@lazy null

    @Suppress("UNCHECKED_CAST")
    ptr as CPointer<CFunction<(CValuesRef<posix_spawn_file_actions_t>, CPointer<ByteVarOf<Byte>>) -> Int>>
}

@Throws(UnsupportedOperationException::class)
internal fun FileActions.try_spawn_file_actions_addchdir(directory: File, scope: MemScope): Int = with(scope) {
    ADDCHDIR_NP?.invoke(ref, chdir.path.cstr.ptr)
        ?: throw UnsupportedOperationException()
}