Loading a library at run time
A library linked when the program is built must be present for the program to
start at all. dylibload opens a shared library while the program runs,
so the program can decide what to do when a plugin or an optional library is
missing.
'' Load a library while the program runs, and find a function in it.
#if defined( __FB_WIN32__ )
const LIBNAME = "ucrtbase.dll"
#elseif defined( __FB_DARWIN__ )
const LIBNAME = "libm.dylib"
#else
const LIBNAME = "libm.so.6"
#endif
type MathFn as function cdecl( byval x as float64 ) as float64
dim as any ptr lib_ = dylibload( LIBNAME )
if lib_ = nullptr then
print "could not load the maths library"
end 1
end if
'' dylibsymbol returns an address, or nullptr for a name it lacks.
dim as MathFn root = dylibsymbol( lib_, "sqrt" )
dim as MathFn missing = dylibsymbol( lib_, "no_such_function" )
print "found sqrt: "; cbool( root <> nullptr )
print "found no_such_function: "; cbool( missing <> nullptr )
if root <> nullptr then
print "sqrt( 144 ) ="; root( 144.0 )
end if
'' A library that is not there is a null handle, not a crash.
print "missing library loads: "; _
cbool( dylibload( "no_such_library_here" ) <> nullptr )
dylibfree( lib_ )
Output
found sqrt: true
found no_such_function: false
sqrt( 144 ) = 12
missing library loads: false
| Call | Does |
|---|---|
dylibload( name ) | opens the library and returns a handle, or nullptr |
dylibsymbol( handle, "name" ) | finds a function or variable by name and returns its address, or nullptr |
dylibfree( handle ) | closes the library |
Library names differ by platform: name.dll on Windows, libname.so on Linux,
often with a version number as in libm.so.6, and libname.dylib on macOS.
The example loads the C runtime's maths library on each, chosen with
#if defined( __FB_WIN32__ ) and its #elseifs, and calls its sqrt.
dylibsymbol returns an untyped address. Assigning it to a variable of a
function pointer type, here MathFn, makes it callable, and that type is a
promise exactly as a declare is: nothing checks it. A plugin system usually
agrees on one entry point with a fixed signature, looks that up, and gets
everything else through it.
After dylibfree, every address taken from the library is invalid. Look a
symbol up once and keep the pointer while the library is open; the search
costs time.
Activities
- Look up
cbrtas well and print the cube root of 27. - Make the program print a message and carry on when the library is missing, instead of ending.