Thanks to Duncan Murdoch for help with the R end and Martin Alderson of Salford Software Ltd for help with the FTN95 end.
Naïve use of the Salford compilers seems to generate code which works, in that it can be called and gives the right answers, but leads to unpredictable, but repeatable, crashes of the Rgui at some later time – usually when calling some other function. On loading the DLL you get the warning that the floating point control word (fpcw) has been changed. There is disagreement between the R and Salford as to who is responsible for the fpcw! It seems that if you can make the Salford compiler always return with the fpcw that R wants most of the problems seem to go away.
However R can still crash, and these crashes seem to be connected with loading the DLL and running it within the same command block (ie all seems to be OK if you type at the console or paste in the dll.load line and subsequent calls as separate steps, but if you paste or source the whole code you can get crashes) This suggests that ftn95 is messing with other registers in some way that R is not happy with.
Subroutine calls do use the c_decl calling convention that R requires, and subroutine names are exported in upper-case with no underscores. Using .C() seems slightly more reliable then .Fortran()
How to make ftn95 return the R-compliant fpcw
Each routine that is called from R needs to save and restore the fpcw.
Subroutine mysub(….)
.
.
integer*2 fpcw
! before you do anything save the floating point control word...
code
fstcw fpcw
edoc
!
! code in here
!
! restore the floating point control word just before return
code
fldcw fpcw
edoc
end subroutine mysub
However this doesn’t remove the warning message as the compiler changes the fpcw on initialisation. So you need a libmain function to do this. Ideally you should call the Rwin_fpset function in R.dll, but I couldn’t get this to work. You can link to the R.dll simply by including the R.dll in the project (no need for an import library). Unfortunately the compiler looks for “RWIN_FPSET” not “Rwin_fpset” and fails to resolve the symbol, so we use the actual value instead (which may change) :
integer function libmain@(hinst,ul,lpr)
integer hinst,ul,lpr
! integer*2 status,Rwin_fpset
integer*2 fpcw
LIBMAIN@=1
!restore FPCW
! status=Rwin_fpset() !! --doesn't work - lookes for "RWIN_FPSET" - wrong capitalisation
! so do it by brute force
fpcw = Z'037f'_2
code
fldcw fpcw
edoc
END
This is probably unnecessary as dyn.load resets the fpcw anyway. Don’t forget Ftn95 is a Fortran 95 compiler, but R likes simple subroutine interfaces, with fixed-size arrays – pass the array sizes as arguments!
Last modified: $Date: 2004-02-27 20:00:35 -0500 (Fri, 27 Feb 2004) $, by Duncan Murdoch