How to Call Fortran Routines from S-Plus/R for Windows ====================================================== http://www.math.yorku.ca/Who/Faculty/Monette/S-news/0318.html discussed several methods. This file will discuss two of them: 1. Use f2c + Visual C++ 2. Use Compact Visual Fortran Rice does not have a site license for Visual Fortran and Visual C++. Since Visual C++ is much cheaper than Visual Fortran and is more popular, the first solution is very appealing. f2c + Visual C++ ======================= Translate the fortran code to C ------------------------------- 1. f2c for windows f2c for windows can be downloaded from http://public.activestate.com/gsar/ Decompress and run f2c yourfile.f to translate yourfile.f to yourfile.c 2. f2c on Unix f2c is availabe on stat network, though is well-hidden at /opt/site/f2c-0.1/sunos5/bin/f2c The results of the translations are identical.o 3. Send an email to netlib@research.att.com with content execute f2c ... the fortran program ... Subject line does not matter. Note: Even if you use method 2 or 3, you still need f2c.h and the f2c library for windows from http://public.activestate.com/gsar/. Build a DLL using Visual C++ ----------------------------- For example, your fortran code is ellipse.f, translated file is ellipse.c, you would like to build a library ellip.dll, 1. Start Visual C++ 2. Select File -> New -> Pojects -> Win32 Dynamic Link Library Choose project name ellip. Note: This name will be the name for the generated dll file and should not be the same as the fortran file. Choose "Dll with exported functions..." from the next page. A project will be created. 3. Copy ellipse.c, vcf2c.lib (or libf77.lib, livf2c.lib if you use other version of f2c), f2c.h into the workplace. 4. Add f2c.h into "Header Files" Add ellipse.c into "Source Files" Add vcf2c.lib (or libf77.lib etc) into "Resourses" (?) 5. Go to Project -> Settings Expand "Source Files" from left panel, choose ellipse.c Choose C/C++ from the right panel From the Category combo box, select Precompiled headers Select 'Not using precompiled headers ' 6. Add __declspec(dllexport) before any function that you want to export. (To be accssible from S-Plus/R). Note: This is not the official way. VC recommends PROJECTNAME_API (for our case ELLIP_API) 7. Build ellip.dll Link a DLL to S-Plus/R for windows ---------------------------------- R: (Need verification.) dyn.load("path/to/dll/ellip.dll") .C("ellipse_", parameter) S-Plus: dll.load( "path/to/the/dll/ellip.dll", c("mysub1_","mysub_")) .C("mysub_", parameter) Or better: dll.load( "path/to/dll/ellli.dll", c("mysub1_","mysub_")) # function definitions mysub1 <- function(a,b) { r <- .C("mysub1_", as.double(a),as.double(b)) r } mysub2 <- function(a,b) { r <- .C("mysub2_", as.double(a),as.double(b)) r } Note: In S-Plus, the second parameter of dll.load is VERY important! Without that, none 0f the symbols will be loaded. Compact Visual Fortran ======================= Original Web Page is: http://academic2.american.edu/~jpnolan/Misc/FortranDLL.html Author: John Nolan Professor PhD., University of Virginia Creating a Windows DLL with Visual Fortran -------------------------------------------- First, examine your Fortran code. Fortran I/O statements (and possibly other non-numeric routines) can mess up the runtime environment of many programs that will link to the DLL. I can't remember the problems, but I also gave up using Fortran functions and returning function values. I do every routine as a Fortran subroutine, passing both input variables and output results as variables. As always, try to vectorize things if you want a nice S-Plus routine. Start a new project within Visual Fortran (MS) IDE and select the type as "Fortran Dynamic Link Library". Open the fortran source file. For each routine that you want to have available in the DLL, you need to add a "comment line", starting in column 1, as in the following example: subroutine mysub1(a,b) cDEC$ ATTRIBUTES DLLEXPORT :: MYSUB1 ... subroutine mysub2(a,b) cDEC$ ATTRIBUTES DLLEXPORT :: MYSUB2 This is Compaq Fortran's way of telling the compiler to create an external "entry point" for MYSUB1, etc. (Each routine needs this kind of line, with it's name after the "::". If you don't put this line there, a routine will not be visible in the DLL. It can be used inside your Fortran program, but will not be available for an external program to call.) Build the DLL within the IDE, say nolan.dll. Linking a DLL to S-Plus under Windows --------------------------------------- Use the IDE editor or some editor to create a file, say "c:\folder\nolan.s", like the following: ("c:\folder" should be the folder/directory where you put this stuff. Also note that S-Plus uses the "\" key as an escape key, so don't use it in a filename, use "/".) # S-Plus code to link to Fortran DLL dll.load( "c:/folder/nolan.dll",c("MYSUB1","MYSUB2")) # function definitions mysub1 <- function(a,b) { r <-.Fortran("MYSUB1", as.double(a),as.double(b)) r} mysub2 <- function(a,b) { r <- .Fortran("MYSUB2", as.double(a),as.double(b)) r} This tells S-plus to load the dll, make the entry points MYSUB1 and MYSUB2 available to S-plus, and tells S-Plus what variables to pass. The statements above return a record r, with all the information about the call. In most cases, you only want to return part of the record, say r$a to return the contents of variable a. Start S-Plus, then type source("c:/folder/nolan.s"). This will read the file created above and define the entry points. You must do this every time you start the program. When you call mysub1(a,b), S-plus will attempt to call the dll and execute it's code. If you have the wrong number of arguments, or some other specifiation error, S-Plus may blow up. Hope this helps. helpdesk@stat.rice.edu $Date: 2002/08/08 00:48:16 $