I am writing a little dlopen
-based plugin mechanism and I'd like to show how to implement a "hello world"
plugin in various languages.
Fortran is next. My Fortran days are a bit behind (at the time it was spelled FORTRAN77).
I'd like to do the equivalent C hello world, with Fortran ISO_C_BINDING
mechanism:
#include <stdlib.h>
#include <stdio.h>
typedef struct {
const char *name;
void *svcLocator;
} Alg_t;
// c_alg_new returns a new Alg_t C-algorithm.
void *c_alg_new(const char *name, void *svcLocator) {
Alg_t *ctx = (Alg_t*)malloc(sizeof(Alg_t));
ctx->name = name;
ctx->svcLocator = svcLocator;
return (void*)ctx;
}
// c_alg_del deletes an Alg_t C-algorithm.
void c_alg_del(void *self) {
free(self);
return;
}
int c_alg_ini(void *self) {
Alg_t *ctx = (Alg_t*)self;
fprintf(stdout, ">>> initialize [%s]...\n", ctx->name);
fprintf(stdout, ">>> initialize [%s]... [done]\n", ctx->name);
return 0;
}
int c_alg_exe(void *self) {
Alg_t *ctx = (Alg_t*)self;
fprintf(stdout, ">>> execute [%s]...\n", ctx->name);
fprintf(stdout, ">>> execute [%s]... [done]\n", ctx->name);
return 0;
}
int c_alg_fin(void *self) {
Alg_t *ctx = (Alg_t*)self;
fprintf(stdout, ">>> finalize [%s]...\n", ctx->name);
fprintf(stdout, ">>> finalize [%s]... [done]\n", ctx->name);
return 0;
}
here is what I have right now:
program foo
use, intrinsic :: iso_c_binding, only : c_int, c_ptr, c_char, c_null_char
implicit none (type, external)
type, bind(C) :: Alg
character(kind=c_char) :: name(1000)
type (c_ptr) :: svcloc
end type Alg
!! function f_alg_new() result(ctx)
!! type(Alg) :: ctx
!! end function
end program
the idea is to have another component dlopen
a given .so
, locate some "well known" symbols and require:
- a symbol to instantiate plugin components
- a symbol to delete a plugin component
- a trio of symbols to initialize, execute, finalize plugin components.
the plugin components would be instantiated by the "manager" of plugin components.
I am a bit at loss as how to write the f_alg_new
, f_alg_del
and f_alg_{ini,exe,fin}
Fortran equivalents.
any hint?
EDIT
on the plugin manager side, here is some mock up code:
void foo(void *lib) {
// load "component-new" symbol
void *cnew = dlsym(lib, "f_alg_new");
if (cnew == NULL) { ... }
void *cdel = dlsym(lib, "f_alg_del");
if (cdel == NULL) { ... }
void *cini = dlsym(lib, "f_alg_ini");
if (cini == NULL) { ... }
// etc...
// create a new Fortran, C, Go, ... component
void *ctx = (*cnew)("f-alg-0", NULL);
// initialize it:
int err = (*cini)(ctx);
if (err != 0) { ... }
for (int ievent=0; ievent < NEVTS; ievent++) {
int err = (*cexe)(ctx);
if (err != 0) { ... }
}
// finalize it:
err = (*cfin)(ctx);
if (err != 0) { ... }
// destroy/clean-up
(*cdel)(ctx);
}
memory allocated by the plugin is managed plugin-side (hence the xyz_new
and xyz_del
hooks), and the "main" program only schedules the execution of these hooks on the opaque address returned by the xyz_new
hook.