-
I want to know which libraries the client machine has installed in order to determine which functionality to allow and which build of my native library to load, for example if they have ALSA "libasound.so" in their default library path I'll use my ALSA build of my library, If they have JACK, I'll use my JACK build, if they have both I'll use my both build etc etc. Currently I'm using a hack which tries to load the library as if I will use it and then catches the exception if it failed (thus indicating not installed) // minimal mappings to the libraries
interface Alsa {
String snd_asoundlib_version();
}
interface Jack {
int jack_activate(PointerByReference client);
}
//...
void load() {
try {
LibraryLoader.loadLibrary(Alsa.class, options, "asound");
// System has ALSA!
} catch (LinkageError e) {
// No ALSA!
}
try {
LibraryLoader.loadLibrary(Jack.class, options, "jack");
// System has Jack!
} catch (LinkageError e) {
// No Jack!
}
// etc etc...
} My question is, is there a better way to do this (is this way even safe, since the library is technically loaded though I will never actually use it) and if there isn't, maybe there should be? There is a use case for such a functionality (such as my situation). Many thanks for this library and this discussion, the performance difference and the pleasantness of the APIs between JNA and JNR is astonishing, this library is basically better in every way. 😊 |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 1 reply
-
Gentle ping. I know it's possible to do a basic check if a file exists, but that would mean I'd have to search through all possible library locations myself which may not cover all the edge cases. |
Beta Was this translation helpful? Give feedback.
-
I found a solution to my specific use case for anyone curious about how to solve this, but I still think JNR should have this feature in some way without having to load the library or letting callers have to do tedious file checks like I have done. It's in Kotlin, but the idea comes across, essentially I'm just searching to see if the library (in this case JACK, ie /** `true` if *any* of the passed in [paths] refers to an existing file, `false` otherwise */
@Suppress("NOTHING_TO_INLINE")
private inline fun anyFileExists(paths: Iterable<String>): Boolean = paths.any { path: String ->
File(path).let { it.exists() && it.isFile }
}
/** Check if JACK is installed in its expected locations on Darwin x86-64 and GNU/Linux x86-64, arm and aarch64 */
internal val isJackInstalled: Boolean = platform.run {
val libFile = "libjack" + when (os) {
Platform.OS.LINUX -> ".so"
Platform.OS.DARWIN -> ".dylib"
else -> ""
}
val usrLocalLibPath = "/usr/local/lib/"
val usrLibPath = "/usr/lib/"
val libPath = "/lib/"
val linuxArch = when (cpu) {
Platform.CPU.X86_64 -> "x86_64-linux-gnu"
Platform.CPU.ARM -> "arm-linux-gnueabihf"
Platform.CPU.AARCH64 -> "aarch64-linux-gnu"
else -> ""
}
// basic unix including darwin, order is intentional!
val unixLibPaths = listOf(usrLocalLibPath, usrLibPath, libPath).map { "$it$libFile" }
// linux is unix + all the paths with the corresponding arch since we support multiple arch
val linuxLibPaths = unixLibPaths +
listOf(usrLocalLibPath, usrLibPath, libPath).map { "$it$linuxArch$libFile" }
when (os) {
Platform.OS.LINUX -> when (cpu) {
Platform.CPU.X86_64, Platform.CPU.ARM, Platform.CPU.AARCH64 -> anyFileExists(linuxLibPaths)
else -> false
}
Platform.OS.DARWIN -> when (cpu) {
Platform.CPU.X86_64 -> anyFileExists(unixLibPaths)
else -> false
}
else -> false
}
} This isn't great for those edge cases such as if the user has custom (or different) library locations and it definitely cannot verify that the library will actually work (which can only be done by trying to load the library) but in my testing, it's been a good way to find whether a library exists or not without actually loading it. I haven't done this for Windows, but I suspect it'll be very similar looking code, just checking through the possible default dll locations and seeing if the file exists or not, likely dependent on CPU, like 32 or 64 bit etc. similar to what we did for GNU/Linux in the code above. |
Beta Was this translation helpful? Give feedback.
-
This is addressed by the new |
Beta Was this translation helpful? Give feedback.
I found a solution to my specific use case for anyone curious about how to solve this, but I still think JNR should have this feature in some way without having to load the library or letting callers have to do tedious file checks like I have done.
It's in Kotlin, but the idea comes across, essentially I'm just searching to see if the library (in this case JACK, ie
libjack
) is in any of its expected locations, in which case I can assume it's installed.