Here is a typical usage of function pointers in C. I would like to do something similar in Fortran. I have some ideas, but I would like to know if there is some canonical way to do so.
The function pointers and contexts passed in by the user are stored, then called later.
typedef PetscErrorCode (*TSIFunction)(TS,PetscReal,Vec,Vec,Vec,void*);
PetscErrorCode TSSetIFunction(TS ts,Vec res,TSIFunction f,void *ctx);
The user's function is called back using their context at various later times.
In PETSc, they also make heavy use of string -> function pointer tables. Everything is a plugin, so the user can register their own implementations and they are first-class.
#define PCGAMG "gamg"
PCRegisterDynamic(PCGAMG ,path,"PCCreate_GAMG",PCCreate_GAMG);
This registers the creation routine in an "FList", then PCSetFromOptions() offers the ability to choose this method versus any of the other choices. If the system supports dynamic loading, you can skip the compile-time dependency on the PCCreate_GAMG symbol and just pass NULL, then the symbol will be looked up in the shared library at run time.
Note that this one step beyond a "factory", it's an inversion of control device similar to what Martin Fowler calls "service locator".
Note: this came up in my private correspondence with Jed Brown, where he asked this question to me. I decided to outsource it and see what answers people can come up with.
PROCEDURE(function_template), POINTER :: funcinternally. – Ondřej Čertík Dec 07 '11 at 21:43void*, the user ends up having to write interfaces for library functions themselves. If you implement the library in C, this is enough, but if you implement in Fortran, you have to ensure that the compiler never sees the library's "dummy" INTERFACE at the same time as the user's INTERFACE. – Jed Brown Dec 08 '11 at 05:14void*in Fortran is atransfermethod. See here for an example of usage. The other 3 approaches besides thetransfermethod are "work arrays", "specific derived type instead ofvoid *" and use module variables local to the module. – Ondřej Čertík Dec 08 '11 at 06:49transferto a nonsense type (character (len=1), allocatable) just to call the function. – Jed Brown Dec 09 '11 at 08:35