diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/api/README b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/api/README index 9d7a0cc81..8e1ab81df 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/api/README +++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/api/README @@ -42,6 +42,7 @@ As a final step, delete the original api version branches and rename each of the Code Modifications: for each version, modify the sdrplay_api_h.java class to wrap the SYMBOL_LOOKUP variable using the following changes, so that the code doesn't throw an error on systems that don't have the API installed: + //jextract auto-generated code modified to wrap with exception handler for systems that don't have the library static SymbolLookup SYMBOL_LOOKUP; static @@ -54,10 +55,33 @@ following changes, so that the code doesn't throw an error on systems that don't } catch(Exception e) { - SYMBOL_LOOKUP = null; + if(SDRPlayLibraryHelper.LOADED_FROM_PATH) + { + try + { + SYMBOL_LOOKUP = SymbolLookup.libraryLookup(SDRPlayLibraryHelper.LIBRARY_PATH, LIBRARY_ARENA) + .or(SymbolLookup.loaderLookup()) + .or(Linker.nativeLinker().defaultLookup()); + } + catch(Exception e2) + { + SYMBOL_LOOKUP = null; + } + } + else + { + SYMBOL_LOOKUP = null; + } } } +... and add null checking to the findOrThrow() method ... + if(SYMBOL_LOOKUP == null) + { + throw new UnsatisfiedLinkError("unresolved symbol:" + symbol); + } + + IntelliJ setup 1. Run configuration 2. JVM Option: --enable-native-access=ALL-UNNAMED diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/api/SDRPlayLibraryHelper.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/api/SDRPlayLibraryHelper.java index fb20ccc3f..3a5089b00 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/api/SDRPlayLibraryHelper.java +++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/api/SDRPlayLibraryHelper.java @@ -42,22 +42,22 @@ public class SDRPlayLibraryHelper private static final String SDRPLAY_API_PATH_MAC_OS = "/usr/local/lib/libsdrplay_api.dylib"; private static final String SDRPLAY_API_PATH_MAC_OS_ALTERNATE = "/usr/local/lib/libsdrplay_api.so"; private static final String SDRPLAY_API_PATH_WINDOWS = System.getenv("ProgramFiles") + - "\\SDRplay\\API\\" + (System.getProperty("sun.arch.data.model").contentEquals("64") ? "x64" : "x86") + - "\\" + SDRPLAY_API_LIBRARY_NAME; - private static final String JAVA_LIBRARY_PATH_KEY = "java.library.path"; - public static final boolean LOADED = load(); + "\\SDRplay\\API\\x64\\" + SDRPLAY_API_LIBRARY_NAME; - /** - * Attempts to load the SDRPlay API library from the local system. - * - * @return true if library was loaded successfully. - */ - public static boolean load() + public static final boolean LOADED; + public static final boolean LOADED_FROM_PATH; + public static final Path LIBRARY_PATH = Path.of(getSDRplayLibraryPath()); + + static { + boolean loaded = false; + boolean loadedFromPath = false; + try { System.loadLibrary(SDRPLAY_API_LIBRARY_NAME); - return true; + mLog.info("SDRPLay API library loaded by name [" + SDRPLAY_API_LIBRARY_NAME + "]"); + loaded = true; } catch(Throwable t) { @@ -70,11 +70,13 @@ public static boolean load() try { System.load(libraryPath); - return true; + mLog.info("SDRPLay API library loaded by path [" + libraryPath + "]"); + loaded = true; + loadedFromPath = true; } catch(Throwable t2) { - mLog.warn("Unable to load SDRPlay API native library: " + libraryPath); + mLog.info("SDRPlay API native library not found at " + libraryPath); } } else @@ -83,7 +85,8 @@ public static boolean load() } } - return false; + LOADED = loaded; + LOADED_FROM_PATH = loadedFromPath; } /** @@ -115,9 +118,4 @@ else if(SystemUtils.IS_OS_MAC_OSX) mLog.error("Unrecognized operating system. Cannot identify sdrplay api library path"); return ""; } - - public static void main(String[] args) - { - System.out.println("Loaded: " + SDRPlayLibraryHelper.LOADED); - } } diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/api/v3_07/sdrplay_api_h.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/api/v3_07/sdrplay_api_h.java index dd6501a32..dd5fccf0b 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/api/v3_07/sdrplay_api_h.java +++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/api/v3_07/sdrplay_api_h.java @@ -21,6 +21,7 @@ package io.github.dsheirer.source.tuner.sdrplay.api.v3_07; +import io.github.dsheirer.source.tuner.sdrplay.api.SDRPlayLibraryHelper; import java.lang.foreign.AddressLayout; import java.lang.foreign.Arena; import java.lang.foreign.FunctionDescriptor; @@ -57,6 +58,10 @@ static void traceDowncall(String name, Object... args) { } static MemorySegment findOrThrow(String symbol) { + if(SYMBOL_LOOKUP == null) + { + throw new UnsatisfiedLinkError("unresolved symbol:" + symbol); + } return SYMBOL_LOOKUP.find(symbol) .orElseThrow(() -> new UnsatisfiedLinkError("unresolved symbol: " + symbol)); } @@ -95,7 +100,23 @@ static MemoryLayout align(MemoryLayout layout, long align) { } catch(Exception e) { - SYMBOL_LOOKUP = null; + if(SDRPlayLibraryHelper.LOADED_FROM_PATH) + { + try + { + SYMBOL_LOOKUP = SymbolLookup.libraryLookup(SDRPlayLibraryHelper.LIBRARY_PATH, LIBRARY_ARENA) + .or(SymbolLookup.loaderLookup()) + .or(Linker.nativeLinker().defaultLookup()); + } + catch(Exception e2) + { + SYMBOL_LOOKUP = null; + } + } + else + { + SYMBOL_LOOKUP = null; + } } } diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/api/v3_08/sdrplay_api_h.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/api/v3_08/sdrplay_api_h.java index a402c2ffb..d4f69baf5 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/api/v3_08/sdrplay_api_h.java +++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/api/v3_08/sdrplay_api_h.java @@ -21,6 +21,7 @@ package io.github.dsheirer.source.tuner.sdrplay.api.v3_08; +import io.github.dsheirer.source.tuner.sdrplay.api.SDRPlayLibraryHelper; import java.lang.foreign.AddressLayout; import java.lang.foreign.Arena; import java.lang.foreign.FunctionDescriptor; @@ -57,6 +58,10 @@ static void traceDowncall(String name, Object... args) { } static MemorySegment findOrThrow(String symbol) { + if(SYMBOL_LOOKUP == null) + { + throw new UnsatisfiedLinkError("unresolved symbol:" + symbol); + } return SYMBOL_LOOKUP.find(symbol) .orElseThrow(() -> new UnsatisfiedLinkError("unresolved symbol: " + symbol)); } @@ -95,7 +100,23 @@ static MemoryLayout align(MemoryLayout layout, long align) { } catch(Exception e) { - SYMBOL_LOOKUP = null; + if(SDRPlayLibraryHelper.LOADED_FROM_PATH) + { + try + { + SYMBOL_LOOKUP = SymbolLookup.libraryLookup(SDRPlayLibraryHelper.LIBRARY_PATH, LIBRARY_ARENA) + .or(SymbolLookup.loaderLookup()) + .or(Linker.nativeLinker().defaultLookup()); + } + catch(Exception e2) + { + SYMBOL_LOOKUP = null; + } + } + else + { + SYMBOL_LOOKUP = null; + } } } diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/api/v3_15/sdrplay_api_h.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/api/v3_15/sdrplay_api_h.java index 1a9fa3e28..2710b4862 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/api/v3_15/sdrplay_api_h.java +++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/api/v3_15/sdrplay_api_h.java @@ -21,6 +21,7 @@ package io.github.dsheirer.source.tuner.sdrplay.api.v3_15; +import io.github.dsheirer.source.tuner.sdrplay.api.SDRPlayLibraryHelper; import java.lang.foreign.AddressLayout; import java.lang.foreign.Arena; import java.lang.foreign.FunctionDescriptor; @@ -57,6 +58,10 @@ static void traceDowncall(String name, Object... args) { } static MemorySegment findOrThrow(String symbol) { + if(SYMBOL_LOOKUP == null) + { + throw new UnsatisfiedLinkError("unresolved symbol:" + symbol); + } return SYMBOL_LOOKUP.find(symbol) .orElseThrow(() -> new UnsatisfiedLinkError("unresolved symbol: " + symbol)); } @@ -95,7 +100,23 @@ static MemoryLayout align(MemoryLayout layout, long align) { } catch(Exception e) { - SYMBOL_LOOKUP = null; + if(SDRPlayLibraryHelper.LOADED_FROM_PATH) + { + try + { + SYMBOL_LOOKUP = SymbolLookup.libraryLookup(SDRPlayLibraryHelper.LIBRARY_PATH, LIBRARY_ARENA) + .or(SymbolLookup.loaderLookup()) + .or(Linker.nativeLinker().defaultLookup()); + } + catch(Exception e2) + { + SYMBOL_LOOKUP = null; + } + } + else + { + SYMBOL_LOOKUP = null; + } } }