Beruflich Dokumente
Kultur Dokumente
an introduction
Sigal Blay
Dept. of Statistics and Actuarial Science
Simon Fraser University
October 2004
Motivation:
Speed
Efficient memory management
Using existing C libraries
.C
.Call
.External
I.
Calling C with an integer vector
using .C
/* useC1.c
*/
In R:
> dyn.load("useC1.so")
> a <- 1:10
# integer vector
> a
[1]
9 10
9 10
9 10
> out$b
[1] 11
II.
Calling C with different vector types
using .C
/* useC2.c
*/
In R:
> dyn.load("useC2.so")
> i <- 1:10
# integer vector
# string vector
# logical vector
> i
[1]
> d
[1] 1.0 1.5 2.0
> c
[1] "a" "b" "c"
> l
[1] "TRUE"
"FALSE"
9 10
III.
Sending R integer vectors to C
using .Call
/* useCall1.c
*/
#include <R.h>
#include <Rdefines.h>
SEXP getInt(SEXP myint, SEXP myintVar) {
int Imyint, n; // declare an integer variable
int *Pmyint;
PROTECT(myint = AS_INTEGER(myint));
Imyint = INTEGER_POINTER(myint)[0];
Pmyint = INTEGER_POINTER(myint);
n = INTEGER_VALUE(myintVar);
printf( Printed from C: \n);
printf( Imyint: %d \n", Imyint);
printf( n: %d \n", n);
printf( Pmyint[0], Pmyint[1]: %d %d \n",
Pmyint[0], Pmyint[1]);
UNPROTECT(1);
return(R_NilValue);
}
In R:
> dyn.load("useCall1.so")
> myint<- c(1,2,3)
> out<- .Call("getInt", myint, 5)
Printed from C:
Imyint: 1
n: 5
Pmyint[0], Pmyint[1]: 1 2
> out
NULL
IV.
Reading an R character vector from C
using .Call
/* useCall2.c
*/
#include <R.h>
#include <Rdefines.h>
SEXP getChar(SEXP mychar) {
char *Pmychar[5];
// array of 5 pointers
// to character strings
PROTECT(mychar = AS_CHARACTER(mychar));
// allocate memory:
Pmychar[0] = R_alloc(strlen(CHAR(STRING_ELT(mychar, 0))),
sizeof(char));
Pmychar[1] = R_alloc(strlen(CHAR(STRING_ELT(mychar, 1))),
sizeof(char));
In R:
> dyn.load("useCall2.so")
> mychar <- c("do","re","mi", "fa", "so")
> out <- .Call("getChar", mychar)
Printed from C: do re
V.
Getting an integer vector from C
using .Call
/* useCall3.c
#include <R.h>
#include <Rdefines.h>
SEXP setInt() {
SEXP myint;
int *p_myint;
int len = 5;
// Allocating storage space:
PROTECT(myint = NEW_INTEGER(len));
*/
p_myint = INTEGER_POINTER(myint);
p_myint[0] = 7;
UNPROTECT(1);
return myint;
}
// to work with real numbers, replace
// int with double and INTEGER with NUMERIC
In R:
> dyn.load("useCall3.so")
> out<- .Call("setInt")
> out
[1] 7 0 0 0 0
VI.
Getting a character vector from C
using .Call
/* useCall4.c
*/
#include <R.h>
#include <Rdefines.h>
SEXP setChar() {
SEXP mychar;
PROTECT(mychar = allocVector(STRSXP, 5));
SET_STRING_ELT(mychar, 0, mkChar("A"));
UNPROTECT(1);
return mychar;
}
In R:
> dyn.load("useCall4.so")
> out <- .Call("setChar")
> out
[1] "A" ""
""
""
""
VII.
Getting a list from C
using .Call
/* useCall5.c
*/
#include <R.h>
#include <Rdefines.h>
SEXP setList() {
int *p_myint, i;
double *p_double;
SEXP mydouble, myint, list, list_names;
char *names[2] = {"integer", "numeric"};
In R:
> dyn.load("useCall5.so")
> out <- .Call("setList")
> out
$integer
[1] 1 2 3 4 5
$numeric
[1] 1.00000 0.50000 0.33333 0.25000 0.20000