About me | pbdR Tech | HPSC | Phyloclustering | R_note |

R_note -- The Exploration of Statistical Software R (統計軟體 R 深度歷險)
About R_note
Reference
MS Windows

Batch jobs
Function
Data/MySQL
Plot
String/Parse

Remark Lines
Classes/S3
S4 Methods
Batch more
Environment

Good Coding
Fast Loop
LAM/MPI/Rmpi
Recursion

PHP Call R
Basic C
R Call Fortran/C
R Call GSL
C Call R API
C Call R Objects
Standalone

Make Packages
C Pointer
Debug




Section: R Call Fortran/C

  • Reference
    Read the web page The R Manuals.
    The PDF document Writing R Extensions (Chapter 4) in The R Manuals (my mirror here).

  • Call Fortran
    First, create a Fortran code file "call_f.f" contains this

        
    c File name: call_f.f
    c For dynamical loading, compile by g77.
    c SHELL> g77 -c call_f.f ; g77 -shared -o call_f.so call_f.o
    
          subroutine hello(m, a, b, c, d)
            integer i, m
            real*8 a(m), b(m), c(m), d
    
            d = 0
            do i = 1, m
              c(i) = a(i) + b(i)
              d = d + c(i)
              a(i) = 0
            end do
    
            return
          end
    
    c Output is a shared library "call_f.so" can be called by R.
    
         or for MS Windows will like this
        
    c File name: call_f.f
    c For dynamical loading, compile by Compaq Visual Fortran.
    c Here, for fortran 77 syntex.
    
          subroutine hello(m, a, b, c, d)
    cDEC$ ATTRIBUTES DLLEXPORT::hello
    cDEC$ ATTRIBUTES C, REFERENCE, ALIAS:'hello_'::hello
            integer i, m
            real*8 a(m), b(m), c(m), d
    
            d = 0
            do i = 1, m
              c(i) = a(i) + b(i)
              d = d + c(i)
              a(i) = 0
            end do
    
            return
          end
    
    c Output is a shared library "call_f.dll" can be called by R.
    c For fortran 90 syntex, use "!DEC$" to replace "cDEC$".
    

    Create an R code file "call_f.r" contains this

        
    # File name: call_f.r
    
    dyn.load("call_f.so")
    # For MS Windows, it will be like this
    # dyn.load("C:/Windows/Desktop/call_f.dll")
    
    symbol.For("hello")
    is.loaded(symbol.For("hello"))
    
    a <- 1 : 9
    
    test.f <- function(a) {
      b <- a
      d <- vector(mode = "numeric", length = length(a))
      e <- vector(mode = "numeric", length = 1)
      ret <- .Fortran("hello", m = length(a), a = as.double(a),
               b = as.double(b), d = as.double(d), e = as.double(e))
      ret
    }
    
    test.f(a)
    
    dyn.unload("call_f.so")
    # For MS Windows, it will be like this
    # dyn.unload("C:/Windows/Desktop/call_f.dll")
    


  • More about C for MS Windows
    In MS Windows you can use Compaq Visual Fortran to compile call_f.f as call_f.dll and the dll can be called by R.
    See the detail in Using Fortran with R in Windows (my mirror here).
    About mixed language, see Markus Faust's mixed language programing (my mirror here).
    For testing, you can download my compiled example "call_f.dll" to "C:\Windows\Desktop\".

  • Call C
    First, create an C code file "call_c.c" contains this

        
    /*
      File name: call_c.c
      For dynamical load compile by gcc.
      SHELL> gcc -c call_c.c ; gcc -shared -o call_c.so call_c.o
    */
    
    void hello(int m, double *a, double *b, double *c, double *d){
      int i;
    
      d = 0;
      for(i = 0; i < m; i++){
        c[i] = a[i] + b[i];
        *d =+ c[i];
        a[i] = 0;
      }
    }
    
    /* Output is a shared library "call_c.so" can be called by R. */
    

    Create an R code file "call_c.r" contains this

        
    # File name: call_c.r
    
    dyn.load("call_c.so")
    # For MS Windows, it will be like this
    # dyn.load("C:/Windows/Desktop/call_c.dll")
    
    symbol.C("hello")
    is.loaded(symbol.C("hello"))
    
    a <- 1 : 9
    
    test.c <- function(a) {
      b <- a
      d <- vector(mode = "numeric", length = length(a))
      e <- vector(mode = "numeric", length = 1)
      ret <- .C("hello", m = length(a), a = as.double(a),
               b = as.double(b), d = as.double(d), e = as.double(e))
      ret
    }
    
    test.c(a)
    
    dyn.unload("call_c.so")
    # For MS Windows, it will be like this
    # dyn.unload("C:/Windows/Desktop/call_c.dll")
    


  • More about C for MS Windows
    In MS Windows you can use C++Builder to compile "call_c.c" as "call_c.dll" and the dll can be called by R.
    See the detail in Uffe's DLL example (my mirror here).
    For testing, you can download my compiled example "call_c.dll" to "C:\Windows\Desktop\".

  • Output

        
    $m
    [1] 9
    
    $a
    [1] 0 0 0 0 0 0 0 0 0
    
    $b
    [1] 1 2 3 4 5 6 7 8 9
    
    $d
    [1]  2  4  6  8 10 12 14 16 18
    
    $e
    [1] 90
    


  • Conclusion
    Call by address in Fortran.
    Call by value in C.
    Call by value in R function.

    Call by address for R external??
    The function .C() and .Fortran() have a default option "DUP = TRUE" which will copy the object in R and pass the address of duplication to C. If you know how to handle the memory carefully in C, you can set "DUP = FALSE" which will directly pass the address to C without duplication. See the section "C Call R Objects".

  • More
    About Fortran and C, you can read the chapter 16 in S-Plus 2000 Programer's Guide (my mirror here). For MS Windows users, you can read this, Using external compilers with R in Windows (my mirror here).

    For calling other computer languages, such as Tcl/Tk, Java, Perl, Python, ... etc, see omegahat for detail.




[ Go to top ]

Maintained: Wei-Chen Chen
E-Mail: wccsnow @ gmail.com
Last Revised: Dec 12 2016, 09:44 (CST Taipei, Taiwan)
Created: Oct 06 2003
free counters Best Resolution
IE6.0
1280x1024
small font