TABLE OF CONTENTS


libplugin/plugins [ package ]

[ 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

libplugin/Load_plugin [ function ]

[ 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)

libplugin/Plugin_function [ function ]

[ 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)

libplugin/Plugin_function_name [ function ]

[ 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)

libplugin/Plugin_function_names [ function ]

[ 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)

libplugin/Plugin_n_functions [ function ]

[ 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)

libplugin/Set_plugin_diag [ function ]

[ 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)

libplugin/Unload_plugin [ function ]

[ 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)