12

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.

Tlatwork
  • 1,445
  • 12
  • 35
  • When you say you want to fill `target`, are you wanting to flatten the list to make a single-dimensional array, or create a ragged array? This could help make a complete answer. There are several typos and you haven't quite used `INTEGER` the right way to access the elements of `vec`, so while as of now I could add an answer that fixes those things and makes your code compilable, I don't know if it would accomplish what you want. Can you add more clarifying info as to the objective you want to accomplish with the function? – duckmayr Apr 29 '18 at 13:17
  • thanks for your comment. The list should not be flattened. I made an edit to clarify the desired Output. Hope it helps. The question might be actually be very easy, i am very new to C :/ – Tlatwork Apr 29 '18 at 14:02

1 Answers1

10

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
nicola
  • 24,005
  • 3
  • 35
  • 56
  • works for me thanks! Will have to wait a few more hours to Award the bounty though. A minor difference for me: (Instead of `malloc(sizeof(int *)*l);` i have to use `(int **)malloc(sizeof(int *)*l);` to make it work. – Tlatwork Apr 30 '18 at 08:36
  • Note; a nice alternative to `target = malloc(sizeof(int *)*l);` is `target = malloc(sizeof *target * l);` which is easier to code right, review and maintain. – chux - Reinstate Monica May 05 '18 at 17:09
  • @ThanksGuys Concerning "i have to use `(int **)malloc(sizeof(int *)*l);`": what C compiler are you using? Or are you using a non-C compiler like C++? – chux - Reinstate Monica May 05 '18 at 17:11
  • About casting `malloc`, one of the most famous SO questions: https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc – nicola May 06 '18 at 05:16
  • ah well :) Thanks a lot, i learned a lot from your answer. I tried to adapt the code to process strings, but got stock after a few hours. I know it is a new idea. Therefore, I created a new question: https://stackoverflow.com/questions/50231159/process-list-of-strings-from-r-to-c. I would be very thankful for any hints :) Thanks a lot again! – Tlatwork May 08 '18 at 10:19