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