views:

306

answers:

3

What is the simplest possible C function for starting the R interpreter, passing in a small expression (eg, 2+2), and getting out the result? I'm trying to compile with MingW on Windows.

+2  A: 
Dirk Eddelbuettel
True, but that is C++... I'd rather a C example for the moment. Rcpp looks very simple to use, though.
jsight
Yes, I edited accordingly. Inline works fine without Rcpp though. But once you actually want to exchange data, I'd go Rcpp even though you may feel that C++ is more complex than C. It doesn't have to be.
Dirk Eddelbuettel
That's interesting, but the opposite of what I am looking for. I am interested in calling R from (possibly legacy) C code, not the other way around... I'm sorry if the original question wasn't clear. This info is helpful too, though. :)
jsight
Oh, I misunderstood. In that case, try 'littler' and 'RInside' and I will amend my answer.
Dirk Eddelbuettel
+2  A: 

You want to call R from C?

Look at section 8.1 in the Writing R Extensions manual. You should also look into the "tests" directory (download the source package extract it and you'll have the tests directory). A similar question was previously asked on R-Help and here was the example:

#include <Rinternals.h> 
#include <Rembedded.h> 

SEXP hello() { 
  return mkString("Hello, world!\n"); 
} 

int main(int argc, char **argv) { 
  SEXP x; 
  Rf_initEmbeddedR(argc, argv); 
  x = hello(); 
  return x == NULL;             /* i.e. 0 on success */ 
} 

The simple example from the R manual is like so:

 #include <Rembedded.h>

 int main(int ac, char **av)
 {
     /* do some setup */
     Rf_initEmbeddedR(argc, argv);
     /* do some more setup */

     /* submit some code to R, which is done interactively via
         run_Rmainloop();

         A possible substitute for a pseudo-console is

         R_ReplDLLinit();
         while(R_ReplDLLdo1() > 0) {
         /* add user actions here if desired */
        }

      */
     Rf_endEmbeddedR(0);
     /* final tidying up after R is shutdown */
     return 0;
 }

Incidentally, you might want to consider using Rinside instead: Dirk provides a nice "hello world" example on the project homepage.

In you're interested in calling C from R, here's my original answer:

This isn't exactly "hello world", but here are some good resources:

Shane
Many thanks... I was missing the R init function calls... oops. The examples from you (and others) have been extremely help (too bad I can't give accepted answers to a few others too... :) ).
jsight
+1  A: 

Here you go. It's the main function, but you should be able to adapt it to a more general purpose function. This example builds an R expression from C calls and also from a C string. You're on your own for the compiling on windows, but I've provided compile steps on linux:

 /* simple.c */
 #include <Rinternals.h>
 #include <Rembedded.h>
 #include <R_ext/Parse.h>
 int
 main(int argc, char *argv[])
 {
    char *localArgs[] = {"R", "--no-save","--silent"};
    SEXP e, tmp, ret;
    ParseStatus status;
    int i;

    Rf_initEmbeddedR(3, localArgs);

    /* EXAMPLE #1 */

    /* Create the R expressions "rnorm(10)" with the R API.*/
    PROTECT(e = allocVector(LANGSXP, 2));
    tmp = findFun(install("rnorm"), R_GlobalEnv);
    SETCAR(e, tmp);
    SETCADR(e, ScalarInteger(10));

    /* Call it, and store the result in ret */
    PROTECT(ret = R_tryEval(e, R_GlobalEnv, NULL));

    /* Print out ret */
    printf("EXAMPLE #1 Output: ");
    for (i=0; i<length(ret); i++){
        printf("%f ",REAL(ret)[i]);
    }
    printf("\n");

    UNPROTECT(2);


    /* EXAMPLE 2*/

    /* Parse and eval the R expression "rnorm(10)" from a string */
    PROTECT(tmp = mkString("rnorm(10)"));
    PROTECT(e = R_ParseVector(tmp, -1, &status, R_NilValue));
    PROTECT(ret = R_tryEval(VECTOR_ELT(e,0), R_GlobalEnv, NULL));

    /* And print. */
    printf("EXAMPLE #2 Output: ");
    for (i=0; i<length(ret); i++){
        printf("%f ",REAL(ret)[i]);
    }
    printf("\n");

    UNPROTECT(3);
    Rf_endEmbeddedR(0);
    return(0);
 }

Compile steps:

$ gcc -I/usr/share/R/include/ -c -ggdb simple.c
$ gcc -o simple simple.o  -L/usr/lib/R/lib -lR
$ LD_LIBRARY_PATH=/usr/lib/R/lib R_HOME=/usr/lib/R ./simple
EXAMPLE #1 Output: 0.164351 -0.052308 -1.102335 -0.924609 -0.649887 0.605908 0.130604 0.243198 -2.489826 1.353731
EXAMPLE #2 Output: -1.532387 -1.126142 -0.330926 0.672688 -1.150783 -0.848974 1.617413 -0.086969 -1.334659 -0.313699
Jeff