Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Process list from R to C and access it

Tags:

c

r

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.

like image 905
Tlatwork Avatar asked Apr 27 '18 12:04

Tlatwork


1 Answers

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
like image 104
nicola Avatar answered Nov 07 '22 15:11

nicola