#1964 Mac OS issue when loading SDRPlay API native library from fully qualified path. (#1965)

Co-authored-by: Dennis Sheirer <dsheirer@github.com>
This commit is contained in:
Denny Sheirer
2024-09-02 05:11:03 -04:00
committed by GitHub
parent d7fbbcefc5
commit 298d9d7016
5 changed files with 108 additions and 23 deletions

View File

@@ -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 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: 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 //jextract auto-generated code modified to wrap with exception handler for systems that don't have the library
static SymbolLookup SYMBOL_LOOKUP; static SymbolLookup SYMBOL_LOOKUP;
static static
@@ -54,10 +55,33 @@ following changes, so that the code doesn't throw an error on systems that don't
} }
catch(Exception e) 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 IntelliJ setup
1. Run configuration 1. Run configuration
2. JVM Option: --enable-native-access=ALL-UNNAMED 2. JVM Option: --enable-native-access=ALL-UNNAMED

View File

@@ -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 = "/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_MAC_OS_ALTERNATE = "/usr/local/lib/libsdrplay_api.so";
private static final String SDRPLAY_API_PATH_WINDOWS = System.getenv("ProgramFiles") + 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\\x64\\" + SDRPLAY_API_LIBRARY_NAME;
"\\" + SDRPLAY_API_LIBRARY_NAME;
private static final String JAVA_LIBRARY_PATH_KEY = "java.library.path";
public static final boolean LOADED = load();
/** public static final boolean LOADED;
* Attempts to load the SDRPlay API library from the local system. public static final boolean LOADED_FROM_PATH;
* public static final Path LIBRARY_PATH = Path.of(getSDRplayLibraryPath());
* @return true if library was loaded successfully.
*/ static
public static boolean load()
{ {
boolean loaded = false;
boolean loadedFromPath = false;
try try
{ {
System.loadLibrary(SDRPLAY_API_LIBRARY_NAME); 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) catch(Throwable t)
{ {
@@ -70,11 +70,13 @@ public class SDRPlayLibraryHelper
try try
{ {
System.load(libraryPath); System.load(libraryPath);
return true; mLog.info("SDRPLay API library loaded by path [" + libraryPath + "]");
loaded = true;
loadedFromPath = true;
} }
catch(Throwable t2) catch(Throwable t2)
{ {
mLog.warn("Unable to load SDRPlay API native library: " + libraryPath); mLog.info("SDRPlay API native library not found at " + libraryPath);
} }
} }
else else
@@ -83,7 +85,8 @@ public class SDRPlayLibraryHelper
} }
} }
return false; LOADED = loaded;
LOADED_FROM_PATH = loadedFromPath;
} }
/** /**
@@ -115,9 +118,4 @@ public class SDRPlayLibraryHelper
mLog.error("Unrecognized operating system. Cannot identify sdrplay api library path"); mLog.error("Unrecognized operating system. Cannot identify sdrplay api library path");
return ""; return "";
} }
public static void main(String[] args)
{
System.out.println("Loaded: " + SDRPlayLibraryHelper.LOADED);
}
} }

View File

@@ -21,6 +21,7 @@
package io.github.dsheirer.source.tuner.sdrplay.api.v3_07; 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.AddressLayout;
import java.lang.foreign.Arena; import java.lang.foreign.Arena;
import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.FunctionDescriptor;
@@ -57,6 +58,10 @@ public class sdrplay_api_h {
} }
static MemorySegment findOrThrow(String symbol) { static MemorySegment findOrThrow(String symbol) {
if(SYMBOL_LOOKUP == null)
{
throw new UnsatisfiedLinkError("unresolved symbol:" + symbol);
}
return SYMBOL_LOOKUP.find(symbol) return SYMBOL_LOOKUP.find(symbol)
.orElseThrow(() -> new UnsatisfiedLinkError("unresolved symbol: " + symbol)); .orElseThrow(() -> new UnsatisfiedLinkError("unresolved symbol: " + symbol));
} }
@@ -95,7 +100,23 @@ public class sdrplay_api_h {
} }
catch(Exception e) 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;
}
} }
} }

View File

@@ -21,6 +21,7 @@
package io.github.dsheirer.source.tuner.sdrplay.api.v3_08; 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.AddressLayout;
import java.lang.foreign.Arena; import java.lang.foreign.Arena;
import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.FunctionDescriptor;
@@ -57,6 +58,10 @@ public class sdrplay_api_h {
} }
static MemorySegment findOrThrow(String symbol) { static MemorySegment findOrThrow(String symbol) {
if(SYMBOL_LOOKUP == null)
{
throw new UnsatisfiedLinkError("unresolved symbol:" + symbol);
}
return SYMBOL_LOOKUP.find(symbol) return SYMBOL_LOOKUP.find(symbol)
.orElseThrow(() -> new UnsatisfiedLinkError("unresolved symbol: " + symbol)); .orElseThrow(() -> new UnsatisfiedLinkError("unresolved symbol: " + symbol));
} }
@@ -95,7 +100,23 @@ public class sdrplay_api_h {
} }
catch(Exception e) 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;
}
} }
} }

View File

@@ -21,6 +21,7 @@
package io.github.dsheirer.source.tuner.sdrplay.api.v3_15; 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.AddressLayout;
import java.lang.foreign.Arena; import java.lang.foreign.Arena;
import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.FunctionDescriptor;
@@ -57,6 +58,10 @@ public class sdrplay_api_h {
} }
static MemorySegment findOrThrow(String symbol) { static MemorySegment findOrThrow(String symbol) {
if(SYMBOL_LOOKUP == null)
{
throw new UnsatisfiedLinkError("unresolved symbol:" + symbol);
}
return SYMBOL_LOOKUP.find(symbol) return SYMBOL_LOOKUP.find(symbol)
.orElseThrow(() -> new UnsatisfiedLinkError("unresolved symbol: " + symbol)); .orElseThrow(() -> new UnsatisfiedLinkError("unresolved symbol: " + symbol));
} }
@@ -95,7 +100,23 @@ public class sdrplay_api_h {
} }
catch(Exception e) 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;
}
} }
} }