I would like to call C routines from Fortran under linux as suggested in section 5.6 of the "Writing R extensions" documentation. I'm familiar with Fortran but not with C. I understand the example provided in Fortran: subroutine testit() double precision normrnd, x call rndstart() x = normrnd() call dblepr("X was", 5, x, 1) call rndend() end but I don't understand the purpose of this C wrapper: #include <R.h> void F77_SUB(rndstart)(void) { GetRNGstate(); } void F77_SUB(rndend)(void) { PutRNGstate(); } double F77_SUB(normrnd)(void) { return norm_rand(); } neither how I should compile it. Could anyone explain how I should compile and link the C and Fortran files above, and call the Fortran subroutine from R. Thanks, Gilles
The C wrappers are there to align the linking conventions expected by the Fortran compiler (usually subroutine/function foo has its entry point in the object file indicated by a symbol foo_, but it depends on the platform) to that of the C compiler. (The C compiler just uses the function name.) The wrappers give C functions named whatever is appropriate (eg "foo_") to get an entry point that "call foo" will trigger linking to. Calling the Fortran subroutine from R is via .Fortran() after doing a dyn.load() of the shared object file. Creating the shared object should just be a matter of R CMD SHLIB file1.c file2.f but I've never tried using Fortran and C together. Take a look at the magic built in to the R CMD SHLIB and R CMD COMPILE commands, and at some of the packages that come with R (I just do a "find" for "*.f" in the src tree) if you need examples, eg. src/library/stats. Reid Huntsinger -----Original Message----- From: r-devel-bounces at r-project.org [mailto:r-devel-bounces at r-project.org] On Behalf Of Gilles GUILLOT Sent: Tuesday, June 14, 2005 1:05 PM To: R-devel at stat.math.ethz.ch Subject: [Rd] Calling C from Fortran I would like to call C routines from Fortran under linux as suggested in section 5.6 of the "Writing R extensions" documentation. I'm familiar with Fortran but not with C. I understand the example provided in Fortran: subroutine testit() double precision normrnd, x call rndstart() x = normrnd() call dblepr("X was", 5, x, 1) call rndend() end but I don't understand the purpose of this C wrapper: #include <R.h> void F77_SUB(rndstart)(void) { GetRNGstate(); } void F77_SUB(rndend)(void) { PutRNGstate(); } double F77_SUB(normrnd)(void) { return norm_rand(); } neither how I should compile it. Could anyone explain how I should compile and link the C and Fortran files above, and call the Fortran subroutine from R. Thanks, Gilles ______________________________________________ R-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Thanks for your reply. Am I write if I say that the wrapper shoul be double F77_SUB(mygammafn)(double *x) { return gammafn(*x); } instead of double F77_SUB(mygammafn)(double *x) { return gammafn(x); } the first does not compile. wrapper2.c: In function `mygammafn_': wrapper2.c:6: error: incompatible type for argument 1 of `Rf_gammafn' The second compiles and works fine. But still, I find it very strange as the C function gammafn actually called ( as I can see from /R-2.1.0/src/nmath/gamma.c) is not defined as double gammafn(double *x) but as double gammafn(double x) Am I missing something ? Gilles Le Mercredi 15 Juin 2005 17:06, vous avez ?crit :> I actually deleted a part of my reply, dealing with exactly that. Sorry! > You need to declare the C wrapper to take a pointer to a double ("double > *") rather than a double. C passes by value whereas Fortran passes by > reference; in C you get this effect by passing a pointer to the value > (which is also a value). So you want > > double F77_SUB(mygammafn)(double *x) { return gammafn(x); } > > That should work; if not let me know and I'll look more carefully at > Fortran <-> C conventions. > > Reid Huntsinger > > -----Original Message----- > From: Gilles GUILLOT [mailto:gilles.guillot at inapg.inra.fr] > Sent: Wednesday, June 15, 2005 3:50 AM > To: Huntsinger, Reid > Subject: Re: [Rd] Calling C from Fortran > > > Thanks Reid! > And now if I want to call a C function with arguments, > e.g. to compute the gamma function at x, > my C wrapper is: > > #include <R.h> > #include <Rmath.h> > void F77_SUB(rndstart)(void) { GetRNGstate(); } > void F77_SUB(rndend)(void) { PutRNGstate(); } > double F77_SUB(normrnd)(void) { return norm_rand(); } > double F77_SUB(mygammafn)(double x) { return gammafn(x); } > > And my Fortran is: > subroutine testit() > implicit none > double precision normrnd, x, y, mygammafn > call rndstart() > x = dabs(normrnd()) > write(*,*) 'x=',x > call rndend() > > y = mygammafn(x) > write(*,*) 'y=',y > end > > And it does not work, all calls of testit return the same y value. > What is incorrect in my files ? > > > Gilles > > > > > > --------------------------------------------------------------------------- >--- Notice: This e-mail message, together with any attachments, contains > information of Merck & Co., Inc. (One Merck Drive, Whitehouse Station, New > Jersey, USA 08889), and/or its affiliates (which may be known outside the > United States as Merck Frosst, Merck Sharp & Dohme or MSD and in Japan, as > Banyu) that may be confidential, proprietary copyrighted and/or legally > privileged. It is intended solely for the use of the individual or entity > named on this message. If you are not the intended recipient, and have > received this message in error, please notify us immediately by reply > e-mail and then delete it from your system. > --------------------------------------------------------------------------- >----- _________________________________________________________________________ Gilles GUILLOT INRA -D?partement Math?matiques et Informatique Appliqu?es Unit? Mixte de Recherche INRA - INAPG - ENGREF Institut National Agronomique de Paris-Grignon 16, rue Claude Bernard 75231 Paris cedex 5 France phone 33 1 44 08 18 42 fax 33 1 44 08 16 66 http://www.inapg.fr/ens_rech/mathinfo/personnel/guillot/welcome.html
(Forgot to post.) Yes, that was a typo, and the reason is the same; the C function expects a value rather than its address. That's why you can't use it directly from Fortran (aside from naming issues) but it's fine in C. Reid Huntsinger -----Original Message----- From: Gilles GUILLOT [mailto:gilles.guillot at inapg.inra.fr] Sent: Wednesday, June 15, 2005 11:50 AM To: R-devel at lists.R-project.org Cc: Huntsinger, Reid Subject: Re: [Rd] Calling C from Fortran Thanks for your reply. Am I write if I say that the wrapper shoul be double F77_SUB(mygammafn)(double *x) { return gammafn(*x); } instead of double F77_SUB(mygammafn)(double *x) { return gammafn(x); } the first does not compile. wrapper2.c: In function `mygammafn_': wrapper2.c:6: error: incompatible type for argument 1 of `Rf_gammafn' The second compiles and works fine. But still, I find it very strange as the C function gammafn actually called ( as I can see from /R-2.1.0/src/nmath/gamma.c) is not defined as double gammafn(double *x) but as double gammafn(double x) Am I missing something ? Gilles Le Mercredi 15 Juin 2005 17:06, vous avez ?crit :> I actually deleted a part of my reply, dealing with exactly that. Sorry! > You need to declare the C wrapper to take a pointer to a double ("double > *") rather than a double. C passes by value whereas Fortran passes by > reference; in C you get this effect by passing a pointer to the value > (which is also a value). So you want > > double F77_SUB(mygammafn)(double *x) { return gammafn(x); } > > That should work; if not let me know and I'll look more carefully at > Fortran <-> C conventions. > > Reid Huntsinger > > -----Original Message----- > From: Gilles GUILLOT [mailto:gilles.guillot at inapg.inra.fr] > Sent: Wednesday, June 15, 2005 3:50 AM > To: Huntsinger, Reid > Subject: Re: [Rd] Calling C from Fortran > > > Thanks Reid! > And now if I want to call a C function with arguments, > e.g. to compute the gamma function at x, > my C wrapper is: > > #include <R.h> > #include <Rmath.h> > void F77_SUB(rndstart)(void) { GetRNGstate(); } > void F77_SUB(rndend)(void) { PutRNGstate(); } > double F77_SUB(normrnd)(void) { return norm_rand(); } > double F77_SUB(mygammafn)(double x) { return gammafn(x); } > > And my Fortran is: > subroutine testit() > implicit none > double precision normrnd, x, y, mygammafn > call rndstart() > x = dabs(normrnd()) > write(*,*) 'x=',x > call rndend() > > y = mygammafn(x) > write(*,*) 'y=',y > end > > And it does not work, all calls of testit return the same y value. > What is incorrect in my files ? > > > Gilles > > > > > >--------------------------------------------------------------------------->--- Notice: This e-mail message, together with any attachments, contains > information of Merck & Co., Inc. (One Merck Drive, Whitehouse Station, New > Jersey, USA 08889), and/or its affiliates (which may be known outside the > United States as Merck Frosst, Merck Sharp & Dohme or MSD and in Japan, as > Banyu) that may be confidential, proprietary copyrighted and/or legally > privileged. It is intended solely for the use of the individual or entity > named on this message. If you are not the intended recipient, and have > received this message in error, please notify us immediately by reply > e-mail and then delete it from your system. >--------------------------------------------------------------------------->----- _________________________________________________________________________ Gilles GUILLOT INRA -D?partement Math?matiques et Informatique Appliqu?es Unit? Mixte de Recherche INRA - INAPG - ENGREF Institut National Agronomique de Paris-Grignon 16, rue Claude Bernard 75231 Paris cedex 5 France phone 33 1 44 08 18 42 fax 33 1 44 08 16 66 http://www.inapg.fr/ens_rech/mathinfo/personnel/guillot/welcome.html