- Reference
Read the web page The R Manuals
PDF document Writing R Extensions (Chapter 5) in The R Manuals
(my mirror here).
-
Sigal Blay's web space (my mirror
here).
- Steps
1. In R, there are two methods to directly pass the R objects to C,
.Call() and .External().
2. In C, there are two methods to handle R objects by including
"Rdefines.h" and "Rinternals.h" as the header files.
3. R objects use a structure type SEXP as a pointer in C.
1. Allocate R objects.
2. Protect R objects.
3. Duplicate Objects passed from R if any modification is required.
Any objects passed from R should be read-only.
4. After any computing, copy the results to R objects.
5. Unprotect R objects.
4. Return R objects to R from C.
At the following, only .Call() and "Rinternals.h" are demonstrated and
R's list and array will be passed to C.
- Example 1
Available C file:
"callRobj.c".
This is a poisoned vitamin C example discussed with
Dr. Karin S. Dorman
for modifying a C pointer permanently inside an internal function.
Also, an R "list" object is allocated in C.
This object store and return a modified version of input to R.
```
#include
#include
void vitamin_c(SEXP R_n, int **C_n){
*C_n = INTEGER(R_n);
}
SEXP poison(SEXP R_n){
int i, *C_n_1, *C_n_2;
double *C_new_1, *C_new_2;
SEXP new_1, new_2, ret, ret_names;
char *names[2] = {"new.1", "new.2"};
/* Both have the same results. */
vitamin_c(R_n, &C_n_1);
C_n_2 = INTEGER(R_n);
/* protect R objects in C. */
PROTECT(new_1 = allocVector(REALSXP, 1));
PROTECT(new_2 = allocVector(REALSXP, 1));
PROTECT(ret = allocVector(VECSXP, 2));
PROTECT(ret_names = allocVector(STRSXP, 2));
/* set a list object for R. */
SET_VECTOR_ELT(ret, 0, new_1);
SET_VECTOR_ELT(ret, 1, new_2);
/* set list's names for R. */
for(i = 0; i < 2; i++){
SET_STRING_ELT(ret_names, i, mkChar(names[i]));
}
setAttrib(ret, R_NamesSymbol, ret_names);
/* assign points to R objects. */
C_new_1 = REAL(new_1);
C_new_2 = REAL(new_2);
/* update for return to R. */
*C_new_1 = (double) (*C_n_1 + 1);
*C_new_2 = (double) (*C_n_2 + 1);
/* unprotect for R. */
UNPROTECT(4);
return(ret);
}
```
- Outputs
```
> a <- 1
> ret <- .Call("poison", as.integer(a))
> ret
$new.1
[1] 2
$new.2
[1] 2
```
- Conclusion
- Call by address in C.
- Call by address in R when .Call()
and
.External()
are used.
---