Using Fortran with R in Windows
General instructions for working with Fortran are in the Writing R Extensions manual in the docs
subdirectory of the R installation. Instructions that work with the g77 compiler are
given in the readme.packages file in the src/gnuwin32 subdirectory; some additional
tips are given below.
Contents
Back to main list
These notes were written by Martyn Byng.
To solve the problem I basically created the DLL as a fortran dynamic linked
library project, and added the two `!DEC' commands to the subroutine I
wished to add to the DLL. The first (DLLEXPORT), just informs the compiler
to export that routine to the DLL, the second defines the calling convention
(C => cdecl) and adds an underscore to the routine name after it has been
exported (the ALIAS command).
SUBROUTINE ZTEST(A,B,C,D,E,F,G)
!DEC$ ATTRIBUTES DLLEXPORT :: ZTEST
!DEC$ ATTRIBUTES C, ALIAS:'ZTEST_' :: ZTEST
INTEGER A,B,C,D,E,F,G
END
[Later...]
Having now tried this with a more complex routine, it appears that you also
need to add the option REFERENCE to the !DEC commands, i.e. use
!DEC$ ATTRIBUTES C, REFERENCE, ALIAS:'ZTEST_' :: ZTEST
instead of
!DEC$ ATTRIBUTES C, ALIAS:'ZTEST_' :: ZTEST
if you wish to pass vectors to the routine.
These notes were written by J.R.M. Hosking.
Using Fortran routines from R with CVF
1. Take a working Fortran subroutine, and put its name in an
ATTRIBUTES DLLEXPORT directive to ensure that the routine name
is exported from the DLL that will be built. Example:
SUBROUTINE MYSUB(X,N,XMEAN)
CDEC$ ATTRIBUTES DLLEXPORT :: MYSUB
IMPLICIT DOUBLE PRECISION (A-H,O-Z)
DOUBLE PRECISION X(N)
XMEAN=0D0
DO 10 J=1,N
XMEAN=XMEAN+X(J)
10 CONTINUE
XMEAN=XMEAN/N
RETURN
END
2. Compile and link the routine using the CVF options /assume:underscore
and /dll. E.g., supposing that the routine is in a file rtest.f,
at the command prompt type
df rtest.f /assume:underscore /dll
This will create a file rtest.dll file that should be kept, and
.obj, .lib and .exp files that are not needed for R and can be deleted.
(/assume:underscore is needed because R expects that a routine name
exported from a DLL will have an underscore appended to it, but CVF
does not do this by default.)
3. Now from an R command prompt, use dyn.load to load the DLL and
.Fortan("MYSUB",...) to call the function. Example:
> dyn.load("E:\\rtest.dll")
> is.loaded(symbol.For("MYSUB"))
[1] TRUE
> x<-1:6
> .Fortran("MYSUB",as.double(x),as.integer(length(x)),xmean=double(1))
[[1]]
[1] 1 2 3 4 5 6
[[2]]
[1] 6
$xmean
[1] 3.5
>
Note: Fortran 90 constructions can be used within the routine, e.g.
the MYSUB routine could be written as
Subroutine mysub(x,n,xmean)
!DEC$ ATTRIBUTES DLLEXPORT :: MYSUB
Implicit Double Precision (a-h,o-z)
Double Precision x(n)
xmean=Sum(x)/n
Return
End
... but Fortran 90 constructions involving the arguments will not work.
E.g. this version will cause R (ver. 1.5.1) to crash:
Subroutine mysub(x,xmean)
!DEC$ ATTRIBUTES DLLEXPORT :: MYSUB
Implicit Double Precision (a-h,o-z)
Double Precision x(:)
xmean=Sum(x)/Size(x)
Return
End
Some quick tips:
- This compiler exports subroutine names in lowercase, with an underscore
appended (i.e. "DC" would be exported as "dc_".) .Fortran('dc', ...) will
find the routine (it adds the underscore automatically), but an uppercase call will not.
- The easiest way to build a DLL from only one source file is
g77 --shared -o source.dll source.f
For a more complicated DLL using multiple source files, it's probably worthwhile to
set up your files as a package, and use "Rcmd SHLIB", "Rcmd INSTALL", or "Rcmd CHECK".
See the Writing R Extensions manual for details.
Last modified: April 24, 2003, by Duncan Murdoch