Search code examples
wolfram-mathematicafortranmathlink

How to use FORTRAN subroutines or functions in Mathematica?


I'm interested in calling fortran codes in a Mathematica session. I learn that Mathlink offers a way to do that. But I have little knowledge on C and nothing on C++. Is anybody willing to give me a detailed example?

I'm using with Mathematica 8, MS Visual Studio 2008 and Intel Fortran 11. The system is Windows 7 Home Premium.

Many thanks!


Solution

  • The following is an explicit example which I succeeded using gfortan and gcc with the Windows system:

    I found this blog Adventures in Mathlink. It is helpful with a specific example. I installed MinGW in order to use gfortran and gcc. After installation, one must set PATH in order to use gfortran and gcc without typing the path each time. A tip for adding PATH without restarting the system: After adding the PATH, open cmd, and run set PATH=C: Then close cmd, whenyou open it again, with echo %PATH%, you will see the new path list. I followed the steps in the linked blog, adapted to Windows, with the tutorial example addtwo:

    The Mathematica codes writing a .bat file and running it to generate the executable

    (* Write a .bat file to compile the MathLink template *.tm, FORTRAN codes *.f and 
    C codes *.c files, and run it to create an executable file. *)
    CreateExeF[s_String] := 
    Module[{dir, libdir, bindir, BatCode, bat}, dir = NotebookDirectory[];
    {libdir, bindir} = StringJoin[
      "\"", $InstallationDirectory, 
     "\\SystemFiles\\Links\\MathLink\\DeveloperKit\\Windows\\CompilerAdditions\\mldev32\\",
      #] & /@ {"lib\\", "bin\\"};
    BatCode = StringJoin[
     "gfortran -c ", #, ".f -o ", #, "f.o
     gcc -c ", #, ".c -o ", #, ".o
     ",
     bindir, "mprep.exe\" ", #, ".tm -o ", #, "tm.c
     gcc -c ", #, "tm.c -o ", #, "tm.o
     gcc ", #, "tm.o ", #, ".o ", #, "f.o ",
     libdir, "ml32i3m.lib\" ", 
     "-lm -lpthread -mwindows -lstdc++ -o ", #
     ] &;
     (* write the .bat file *)
     bat = Export[FileNameJoin[{dir, # <> ".bat"}], BatCode[dir <> #], 
      "string"] &[s];
     (* run the .bat file *)
     Run[bat]]
    

    FORTRAN codes addtwo.f

       subroutine addtwof(i,j,k)
       integer i, j, k
       k = i + j
       end
    

    C wrapper addtwo.c

    #include "mathlink.h"
    
    int addtwo(int i, int j) 
    {
      int res;
      addtwof_(&i, &j, &res);
      return res;
    }
    
    #if WINDOWS_MATHLINK
    
    #if __BORLANDC__
    #pragma argsused
    #endif
    
    int PASCAL WinMain( HINSTANCE hinstCurrent, HINSTANCE hinstPrevious, LPSTR lpszCmdLine,     int nCmdShow)
    {
    char  buff[512];
    char FAR * buff_start = buff;
    char FAR * argv[32];
    char FAR * FAR * argv_end = argv + 32;
    
    hinstPrevious = hinstPrevious; /* suppress warning */
    
    if( !MLInitializeIcon( hinstCurrent, nCmdShow)) return 1;
    MLScanString( argv, &argv_end, &lpszCmdLine, &buff_start);
    return MLMain( (int)(argv_end - argv), argv);
    }
    
    #else
    
    int main(int argc, char* argv[])
    {
    return MLMain(argc, argv);
    }
    
    #endif
    

    The template file addtwo.tm is the same as the one in Todd Gayley's tutorial. For completeness, it is also given here:

    :Begin:
    :Function:       addtwo
    :Pattern:        AddTwo[i_Integer, j_Integer]
    :Arguments:      { i, j }
    :ArgumentTypes:  { Integer, Integer }
    :ReturnType:     Integer
    :End:
    
    :Evaluate:       AddTwo::usage = "AddTwo[i, j] gives the sum of two integer numbers i and j."