[ Top ] [ package ]
Synopsis
Fortran anc C callable package to use dynamic libraries (shared objects) at runtime
a "plugin" is a dynamic library (shared object) that contains some special elements
http://github.com/mfvalin/wrapper-code/tree/master/PLUGINS
step 0: declaration
Fortran :
USE ISO_C_BINDING
include 'plugins.inc'
C:
#include <plugins.h>
step 1: Load a dynamic library (shared object)
Fortran :
type(C_PTR) :: handle
handle = load_plugin("my_library_name.so")
C :
void *handle;
handle = load_plugin("my_library_name.so");
step 2: Get number of advertised entry points in dynamic library
Fortran:
integer(C_INT) :: nsym
nsym = plugin_n_functions(handle)
C:
int nsym = plugin_n_functions(handle);
step 3: Get the name of advertised entry point n
Fortran:
type(C_PTR) :: string
integer(C_INT) :: n
string = plugin_function_name(handle,n)
C:
int n;
char *string = plugin_function_name(handle,n);
step 4: Get address of entry point by name and call it
Fortran:
type(C_FUNPTR) :: faddress
character(C_CHAR), dimension(*) :: name
procedure(xxx), pointer :: fptr
faddress = plugin_function(handle,name)
call c_f_procpointer(faddress,fptr)
call fptr(...arguments...)
C:
void *faddress;
char *name;
faddress = plugin_function(handle,name);
.. = (*faddress)(...arguments...);
step n: unload plugin
Fortran:
integer(C_INT) :: status
status = unload_plugin(handle)
C:
int status = unload_plugin(handle);
other : set diagnostics verbosity
Fortran:
integer(C_INT) :: verbose
call set_plugin_diag(verbose)
C:
int verbose;
set_plugin_diag(verbose);
NOTES:
the presence of entry point "EntryList_" is mandatory in a "plugin", it is
a NULL pointer terminated list of pointers to NULL terminated strings
providing the names of the advertised entry points in the plugin
(see examples below)
function "get_symbol_number" is optional and may be used to get the
number of values in "EntryList_" (see Fortran)
if neither "EntryList_" nor "get_symbol_number" is present, plugin_n_functions
will return 0, and the user must then known in advance the names available
before calling "plugin_function"
EXAMPLES
----------------------- Example of C plugin -----------------------
c_compiler -shared -fpic -o libxxx.so xxx.c
#include <stdio.h>
#include <string.h>
char *EntryList_[4] = { "name1","name2",NULL} ;
int name1(int arg){
printf("name1: %d\n",arg);
return(arg);
}
int name2(int arg){
printf("name2: %d\n",arg);
return(arg);
}
int get_symbol_number(){ // function to get number of symbols, optional
return(2);
}
----------------------- Example of Fortran plugin -----------------------
( needs a little more extra code than C )
fortran_compiler -shared -fpic -o libxxx.so xxx.F90
integer function fn1(arg) BIND(C,name='name1f')
integer, intent(IN) :: arg
print *,'Fortran name1 =',arg
fn1 = arg
return
end
integer function fn2(arg) BIND(C,name='name2f')
integer, intent(IN) :: arg
print *,'Fortran name2 =',arg
fn2 = arg
return
end
!
! what follows is boiler plate code
! to be adjusted by user : MAX_NAMES, MAX_NAME_LENGTH, calls to insert_in_name_table in subroutine symbols
module interop
use ISO_C_BINDING
implicit none
! start of user adjusted code
#define MAX_NAMES 2
#define MAX_NAME_LENGTH 8
! end of user adjusted code
type(C_PTR), dimension(MAX_NAMES+1), save, target, BIND(C,name='EntryList_') :: name_table
character(len=1), dimension(MAX_NAME_LENGTH+1,MAX_NAMES), save, target :: names
integer, save :: nargs
contains
subroutine insert_in_name_table(name) ! add name to name table and name pointers
use ISO_C_BINDING
implicit none
character(len=*) :: name
integer :: l
l = len(trim(name)) + 1
nargs = nargs + 1
names(1:l,nargs) = transfer(trim(name)//achar(0) , names, l)
name_table(nargs) = C_LOC(names(1,nargs))
return
end subroutine insert_in_name_table
function symbols() bind(C,name='get_symbol_number') result(number)
use ISO_C_BINDING
implicit none
integer(C_INT) :: number
nargs = 0
! start of user adjusted code
call insert_in_name_table('name1f')
call insert_in_name_table('name2f')
! end of user adjusted code
number = nargs ! return number of arguments
return
end function symbols
end module interop
[ Top ] [ function ]
Synopsis
load a plugin (shared object)
Fortran interface
function Load_plugin(lib) result(handle) BIND(C,name='Load_plugin')
import :: C_CHAR, C_INT, C_PTR
character(C_CHAR), dimension(*), intent(IN) :: lib
type(C_PTR) :: handle
end function Load_plugin
lib : character string, name of shared object
function return : handle (blind pointer to a plugin structure)
the rules for finding "lib" are the rules followed by dlopen (see: man dlopen)
ARGUMENTS
void *Load_plugin(const char *lib)
[ Top ] [ function ]
Synopsis
get address of plugin entry name
if pointer to plugin is NULL, scan all known plugins
Fortran interface
function Plugin_function(handle,fname) result(faddress) BIND(C,name='Plugin_function')
import :: C_PTR, C_FUNPTR, C_CHAR
type(C_PTR), intent(IN), value :: handle
character(C_CHAR), dimension(*), intent(IN) :: fname
type(C_FUNPTR) :: faddress
end function Plugin_function
handle : handle obtained from Load_plugin
name : null terminated string, name of entry
function return : address of requested entry ( void * / type(C_PTR) )
ARGUMENTS
void *Plugin_function(const void *handle, const char *name)
[ Top ] [ function ]
Synopsis
get name of entry number ordinal from plugin entry name table
Fortran interface
function Plugin_function_name(handle,ordinal) result(string) BIND(C,name='Plugin_function_name')
import :: C_PTR, C_INT
type(C_PTR), intent(IN), value :: handle
integer(C_INT), value :: ordinal
type(C_PTR) :: string
end function Plugin_function_name
handle : handle obtained from Load_plugin
ordinal : int, ordinal in entry list of desired name (first entry has ordinal 1)
function return : pointer to the name of requested entry ( char * / type(C_PTR) )
ARGUMENTS
const char* Plugin_function_name(const void *handle, int ordinal)
[ Top ] [ function ]
Synopsis
get list of advertised entry names in a given plugin there is no Fortran interface handle : handle obtained from Load_plugin function return : pointer to the list of names (char**) or NULL if none available
ARGUMENTS
const char* *Plugin_function_names(const void *handle)
[ Top ] [ function ]
Synopsis
find number of functions in a given plugin
Fortran interface
function Plugin_n_functions(handle) result(number) BIND(C,name='Plugin_n_functions')
import :: C_PTR, C_INT
type(C_PTR), intent(IN), value :: handle
integer(C_INT) :: number
end function Plugin_n_functions
handle : handle obtained from Load_plugin
function return : number of symbols advertised in the shared object, 0 if error
ARGUMENTS
int Plugin_n_functions(const void *handle)
[ Top ] [ function ]
Synopsis
set diagnostic verbosity level
Fortran interface
subroutine Set_plugin_diag(level) BIND(C,name='Set_plugin_diag')
import C_INT
integer(C_INT), value :: level
end subroutine Set_plugin_diag
diag : diagnotic verbosity level
0 = silent
1 = verbose
there is no return value
ARGUMENTS
void Set_plugin_diag(int diag)
[ Top ] [ function ]
Synopsis
unload a plugin library
Fortran interface
function Unload_plugin(handle) result(status) BIND(C,name='Unload_plugin')
import :: C_INT, C_PTR
integer(C_INT) :: status
type(C_PTR), intent(IN), value :: handle
end function Unload_plugin
handle : handle obtained from Load_plugin
function return : 0 if no error, -1 if there was an error
ARGUMENTS
int Unload_plugin(void *handle)