Sunday, May 6, 2018

Process list from R to C and access it

Leave a Comment

I would like to use a list in C, that i got from R. I realise the question is very similar to this: Passing a data frame from-to R and C using .call(). However, I fail in storing it in a pointer "*target", from where i would further use it.

R:

.Call("processlist", list(c(1,2), c(1,3,2), c(1,5,4,4))) 

and in C:

#include <Rinternals.h> #include <Rdefines.h>  extern "C" {      SEXP processlist(SEXP lst); }  SEXP processlist(SEXP lst){    SEXP vec  = PROTECT(allocVector(VECSXP, 2));    SET_VECTOR_ELT(vec, 0, VECTOR_ELT(c, 0);    SET_VECTOR_ELT(vec, 1, VECTOR_ELT(c, 1);    SET_VECTOR_ELT(vec, 2, VECTOR_ELT(c, 2);     const lngth = 3;    int *target[lnght];     // Here i want to fill "target", but how?    int *preTarget = INTEGER(vec);     // Bad attempts    target[0] = INTEGER(preTarget[0]);    target[0] = INTEGER(vec[0]); } 

Note: C++ is not an Option unfortunately.

Edit: Desired output would be that I can call *target the following way.

target[0][0] --> Returns: 1 target[1][2] --> Returns: 2 target[2][3] --> Returns: 4 

Calling "vec" in that way throws me an error at the moment.

1 Answers

Answers 1

It seems to me that you just want to access the values in the list from the C side. If that's correct, look at the code below.

In d.c:

/* Including some headers to show the results*/ #include <Rinternals.h> #include <Rdefines.h> #include <R.h> #include <stdlib.h> #include <stdio.h> SEXP processlist(SEXP lst){    int i,l = length(lst);    /* You need an array of arrays, so target will be an int** */     int **target = malloc(sizeof(int *)*l);    for (i=0;i<l;i++) {      target[i] = INTEGER(VECTOR_ELT(lst,i));    }    printf("target[0][0]: %d\n",target[0][0]);    printf("target[1][2]: %d\n",target[1][2]);    printf("target[2][3]: %d\n",target[2][3]);    free(target);    return R_NilValue; } 

The important thing to notice is that target has to be an int**, since it is a pointer to an array of pointers.

In d.R (after d.c has been compiled):

dyn.load("d.so") mylist<-list(c(1,2), c(1,3,2), c(1,5,4,4)) #This is very important: by default 1 in R is double.  #You need to coerce every element of the list to integer. mylist<-lapply(mylist,as.integer) .Call("processlist", mylist) 

Note that we need to coerce each element of the list to integer. The above produces:

target[0][0]: 1 target[1][2]: 2 target[2][3]: 4 
If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment