real function evapol(tu,nu,tv,nv,c,rad,x,y) #### c rad : real function subprogram, defining the boundary of the c approximation domain. must be declared external in the c calling (sub)-program #### double precision function myfunc(x, y, func) double precision x, y, z, v double precision func v = 1.5 z = func(v) myfunc = x * y * z end #### $ g77 -c myfunc.f -o myfunc.o #### $ h2xs -Afn P2f2p #### #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "ppport.h" MODULE = P2f2p PACKAGE = P2f2p #### #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "ppport.h" static SV * userfunc; double userfunc_wrapper(double *x) { int n; double r; dSP; ENTER; SAVETMPS; PUSHMARK(SP); XPUSHs(sv_2mortal(newSVnv(*x))); PUTBACK; n = call_sv(userfunc, G_SCALAR); SPAGAIN; if (n != 1) croak("wrong number of args returned!\n"); r = POPn; PUTBACK; FREETMPS; LEAVE; return r; } // the Fortran function double myfunc_(double *x, double *y, void* func); double myfunc(double x, double y) { double r; r = myfunc_(&x, &y, &userfunc_wrapper); return r; } MODULE = P2f2p PACKAGE = P2f2p double myfunc(x, y, ufunc) double x double y SV * ufunc CODE: userfunc = newSVsv(ufunc); RETVAL = myfunc(x, y); OUTPUT: RETVAL #### LIBS => [''], # e.g., '-lm' OBJECT => '$(O_FILES)', # link all the C files too #### LIBS => ['-lg2c -lm'], # e.g., '-lm' OBJECT => '$(O_FILES) myfunc.o', # link all the C files too #### perl Makefile.PL make make test #### $ mkdir -p /path/to/working/directory/auto/P2f2p $ cp blib/arch/auto/P2f2p/P2f2p.so /path/to/working/directory/auto/P2f2p/ $ cp blib/lib/P2f2p.pm /path/to/working/directory/ #### #!/usr/bin/perl use P2f2p; sub userfunc { my $v = shift; print "userfunc()\n called from Fortran with arg: $v\n"; my $r = $v + 0.5; print " returning: $r\n"; return $r; } my $r = P2f2p::myfunc(3, 7, \&userfunc ); printf "myfunc() returned: %.2f\n", $r; #### userfunc() called from Fortran with arg: 1.5 returning: 2 myfunc() returned: 42.00