I’m trying to write a wrapper to use the gsl library with Fortran. I have managed to get a simple wrapper to work – the example from http://www.helsinki.fi/~fyl_tlpk/luento/ohj-13-GSL-e.html
Fortran code
program gsltest
implicit none
real(kind=selected_real_kind(12)) :: a = 0.11, res
external :: glsgateway
call gslgateway(a,res)
write(*,*) 'x', a, 'atanh(x)', res
end program gsltest
c function
#include <gsl/gsl_math.h>
void gslgateway_(double *x, double *res){
*res = gsl_atanh(*x);
}
That’s all well and good. However, I’m having problems with a more complicated wrapper. I have the following code modified from an example at http://apwillis.staff.shef.ac.uk/aco/freesoftware.html
c wrapper (rng_initialise.c)
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
static gsl_rng* r;
void rng_initialise__(int* s) {
r = gsl_rng_alloc(gsl_rng_taus);
gsl_rng_set(r, (unsigned long int)(*s));
}
Fortran main (main.f90)
PROGRAM main
integer seed
call system_clock(seed)
WRITE (*,*) 'calling rng_initialise'
call rng_initialise(seed)
END PROGRAM main
which I then compile and link by
gcc -c rng_initialise.c
g95 -c main.f90
g95 -o main main.o rng_initialise.o -L/usr/libs -lgsl
When I run this program, I get no output. However, if I comment out the lines inside rng_initialise
...
void rng_initialise__(int* s) {
// r = gsl_rng_alloc(gsl_rng_taus);
// gsl_rng_set(r, (unsigned long int)(*s));
}
then I get output from the Fortran code (it writes ‘calling_rng_initialise’ to STDOUT).
So, the problem seems to be the calls to gsl_rng_alloc and gsl_rng_set. But I don’t get any error messages, and I don’t know why they would prevent the Fortran code from doing anything. Any ideas?
Most likely you have the linkage between the two routines wrong in some way. If the stack isn’t dealt with correctly when you hop through that interface, dang near anything can happen.
I’m not noticing any code on either the Fortran side or the C side specifying the other’s calling convention. I’m not an expert with Gnu Fortran, but I know most compilers will require some kind of note that they should be using another compiler’s calling convention, or Bad Things may happen.
With just a little web searching, I see that the G95 Fortran manual (PDF) has a nice long section titled “Interfacing with G95 Programs”, that appears to go into this in detail. Just from skimming, it looks like you should be using the
BIND(C)attribute on your Fortran function declaration for that C routine.