Using a Salford ftn95 generated dll with R (MS Windows)

These notes were written by Dr Steve Roberts

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