# Calling C from R: The .Call() Interface Jan de Leeuw Version 001 08/04/2016 #Introduction # Numbers ##Vectors ```c #include #include #include SEXP myHypot (SEXP x, SEXP y) { R_len_t nProtected = 0; SEXP z = PROTECT (allocVector (REALSXP, 1)); nProtected++; double *h = REAL (z); *h = hypot (REAL (x)[0], REAL (y)[0]); UNPROTECT (nProtected); return (z); } ``` ```r .Call ("myHypot", as.double(3), as.double (4)) ``` ``` ## [1] 5 ``` ```c #include #include #include SEXP myEnorm (SEXP x) { R_len_t n = length (x), i, nProtected = 0; SEXP z = PROTECT (allocVector (REALSXP, 1)); nProtected++; double *h = REAL (z), *v = REAL(x); for (i = 0; i < n; i++) *h += v[i] * v[i]; *h = sqrt (*h); UNPROTECT (nProtected); return (z); } ``` ```r .Call ("myEnorm", as.double(1:4)) ``` ``` ## [1] 5.477226 ``` ## NA If the vector possibly contains NA's we have to take that into account. The following routine squares the elements of a vector and skips over the NA's. We also allow for the possibility that some elements are not numbers. If they can be converted, this is done. If they cannot be converted, R issues a warning. ```c #include #include SEXP square (SEXP x) { R_len_t i, n = length (x), nProtected = 0; SEXP y = PROTECT (allocVector (REALSXP, n)); nProtected++; double *v = REAL (y), *z; if (TYPEOF (x) == REALSXP) { z = REAL (x); } else { z = REAL (coerceVector (x, REALSXP)); } for (i = 0; i < n; i++) { v[i] = R_NaReal == z[i] ? -1 : z[i] * z[i]; } UNPROTECT (nProtected); return (y); } ``` ```r .Call("square", as.double(c(1, NA, 2, "3", -1))) ``` ``` ## [1] 1 NA 4 9 1 ``` ```r .Call("square", as.double(c(1, NA, 2, "a", -1))) ``` ``` ## Warning: NAs introduced by coercion ``` ``` ## [1] 1 NA 4 NA 1 ``` ##Matrices and Arrays ###From R to C ###From C to R ##Attributes #Characters ##From R to C ##From C to R #Lists ##From R to C ##From C to R #Functions and Expressions ##Calling an R function from C ```c #include #include SEXP myRnorm (SEXP n) { R_len_t nProtected = 0, *m = INTEGER (n); SEXP y = PROTECT (allocVector (REALSXP, *m)); nProtected++; SEXP rnormR = install("rnorm"); y = eval (lang2 (rnormR, ScalarInteger (*m)), R_GlobalEnv); UNPROTECT (nProtected); return (y); } ``` ```r .Call("myRnorm", as.integer(5)) ``` ``` ## [1] 1.0076824 0.7950361 3.1697993 -0.5333102 -0.3884233 ``` ```c #include #include SEXP myFirstN (SEXP n) { R_len_t nProtected = 0, *m = INTEGER (n); SEXP y = PROTECT (allocVector (REALSXP, *m)); nProtected++; SEXP firstR = install("firstN"); y = eval (lang2 (firstR, ScalarInteger (*m)), R_GlobalEnv); UNPROTECT (nProtected); return (y); } ``` ```r firstN <- function (n) 1:n .Call("myFirstN", as.integer(5)) ``` ``` ## [1] 1 2 3 4 5 ``` ##Passing R function to C # Vectors of Characters