The fortran_dynamic_loader
module defines an object-oriented Fortran
interface to the system dynamic loader as implemented by the POSIX C functions
dlopen
, dlclose
, dlsym
, and dlerror
.
use fortran_dynamic_loader
use,intrinsic :: iso_c_binding, only: c_ptr, c_f_pointer
use,intrinsic :: iso_c_binding, only: c_funptr, c_f_procpointer
Defines:
derived type: shlib
subroutines: shlib%open
, shlib%close
, shlib%func
, shlib%sym
parameters: RTLD_LAZY
, RTLD_NOW
, RTLD_LOCAL
, RTLD_GLOBAL
Link with the system DL library (-ldl
on Linux) to
resolve the symbols dlopen
, dlclose
, dlsym
, and dlerror
.
The derived type shlib
implements the dynamic loading of a shared
library and access to data and procedures defined by the library.
The derived type has the following type bound subroutines. Each subroutine has
the optional intent(out)
arguments stat
and errmsg
. If the integer
stat
is present, it is assigned the value 0 if the subroutine completes
successfully, and a nonzero value if an error occurs. In the latter case,
the deferred-length allocatable character variable errmsg
, if present,
is assigned the error string returned by the underlying system dl library.
If stat
is not present and an error occurs, the error string is written
to the preconnected error unit and the program exits with a nonzero status.
open(filename, mode [,stat [,errmsg]])
Load the shared library file named by the character argument filename
and associate it with the shlib
object. If filename
contains a slash
/
it is interpreted as a relative or absolute pathname. Otherwise the
dynamic loader searches a certain list of directories for the library; see
the system documentation for dlopen
for a detailed description of the
search process.
One of the following two parameters must be passed as the mode
argument:
RTLD_LAZY
Only resolve symbols as the code that references them is executed (lazy binding).
RTLD_NOW
All undefined symbols in the library are resolved before the open
procedure returns. An error occurs if this is not possible. This
is also the behavior if the environment variable LD_BIND_NOW
is
set to a nonempty string (Linux).
One of the following parameters may optionally be or’ed with the preceding
values before being passed as the mode
argument; for example,
mode = ior(RTLD_LAZY,RTLD_GLOBAL)
.
RTLD_GLOBAL
The symbols defined by this library will be made available for symbol resolution of subsequently loaded libraries.
RTLD_LOCAL
This is the converse of RTLD_GLOBAL
and the default. Symbols
defined by this library are not made available to resolve references
in subsequently loaded libraries.
See the system documentation for dlopen
for more details.
close([stat [,errmsg]])
Decrement the reference count on the shared library. When the reference
count reaches zero, the shared library is unloaded. See the system
documentation for dlclose
for a detailed description of the behavior.
func(symbol, funptr [,stat [,errmsg]])
Get the memory address where the specified function symbol from the shared
library is loaded. The character argument symbol
gives the symbol name,
and the address is returned in the type(c_funptr)
argument funptr
.
The caller is responsible for converting this C function pointer to an
appropriate Fortran procedure pointer using c_f_procpointer
from the
intrinsic iso_c_binding
module.
sym(symbol, symptr [,stat [,errmsg]])
Get the memory address where the specified data symbol from the shared
library is loaded. The character argument symbol
gives the symbol
name, and the address is returned in the type(c_ptr)
argument
symptr
. The caller is responsible for converting this C pointer
value to an appropriate Fortran data pointer using c_f_pointer
from
the intrinsic iso_c_binding
module.
Load the C math library libm.so and calculate the cube root of 8 using the function cbrtf from the library.
use fortran_dynamic_loader
use,intrinsic :: iso_c_binding, only: c_funptr, c_f_procpointer
abstract interface
real function f(x)
real, value :: x
end function
end interface
procedure(f), pointer :: cbrtf
type(shlib) :: libm
type(c_funptr) :: funptr
call libm%open('libm.so', RTLD_NOW)
call libm%func('cbrtf', funptr)
call c_f_procpointer(funptr, cbrtf)
if (cbrtf(8.0) /= 2.0) print *, 'error'
call libm%close