studio - R desde C-Helloworld más simple posible
text in r (4)
¿Cuál es la función C más simple posible para iniciar el intérprete R, pasar una expresión pequeña (por ejemplo, 2 + 2) y obtener el resultado? Estoy tratando de compilar con MingW en Windows.
¿Quieres llamar a R desde C?
Mire la sección 8.1 en el manual de Writing R Extensions . También debe buscar en el directorio de "pruebas" (descargue el paquete fuente, extráigalo y tendrá el directorio de pruebas). Anteriormente se hizo una pregunta similar en R-Help y aquí estaba el ejemplo :
#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 */
}
El ejemplo simple del manual de R es así:
#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;
}
Por cierto, es posible que desee considerar utilizar Rinside en su lugar: Dirk proporciona un buen ejemplo de "hola mundo" en la página de inicio del proyecto.
En tu interés en llamar a C desde R, aquí está mi respuesta original:
Esto no es exactamente "hola mundo", pero aquí hay algunos buenos recursos:
- Jay Emerson recientemente dio una charla sobre el desarrollo del paquete R en el grupo de uso de Nueva York, y proporcionó algunos ejemplos muy buenos de cómo usar C desde R. Eche un vistazo al documento de esta discusión en su sitio web , comenzando en la página 9. Todos El código fuente relacionado está aquí: http://www.stat.yale.edu/~jay/Rmeetup/MyToolkitWithC/ .
- El curso impartido en Harvard por Gopi Goswami en 2005: C-C ++ - R (en Estadística) . Esto incluye ejemplos extensos y código fuente.
Aqui tienes. Es la función principal, pero debería poder adaptarla a una función de propósito más general. Este ejemplo construye una expresión R a partir de llamadas C y también a partir de una cadena C. Usted está solo para compilar en Windows, pero he proporcionado pasos de compilación en 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);
}
Pasos de compilación:
$ 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
Creo que no puedes hacerlo mucho mejor que el paquete en inline (que admite C, C ++ y Fortran):
library(inline)
fun <- cfunction(signature(x="ANY"),
body=''printf("Hello, world//n"); return R_NilValue;'')
res <- fun(NULL)
que imprimirá ''Hola Mundo'' para ti. Y ni siquiera sabe dónde / cómo / cuándo se invoca el compilador y el vinculador. [El R_NilValue es la versión NULL de R de un SEXP y la firma .Call()
utilizada aquí requiere que devuelvas un SEXP; consulta el manual ''Escribiendo Extensiones R'' que realmente no puedes evitar aquí. ]
Luego tomará dicho código y lo envolverá en un paquete. Tuvimos un gran éxito al usar en inline para las pruebas unitarias de Rcpp (más de 200 y contando ahora) y algunos de los ejemplos.
Ah, y este ejemplo en inline funcionará en cualquier sistema operativo. Incluso Windoze siempre que tenga instalada la cadena de herramientas de construcción de paquetes R, en el PATH, etc. pp.
Edit: He leído mal la pregunta. Lo que quieres es esencialmente lo que hace el front-end RInside (usando C pura) y lo que las clases de RInside eliminaron para C ++.
Jeff y yo nunca nos molestamos en transportar a Windoze, pero RInside trabajó allí en la versión más reciente. Por lo tanto, debería poder hojear las recetas de construcción y crear una variante de RInside solo para C, de modo que pueda alimentar la expresión a un proceso R incrustado. Sospecho que todavía quieres algo como Rcpp para la pista, ya que de lo contrario se vuelve tedioso.
Edit 2: Y, como menciona Shane, hay algunos ejemplos en las fuentes R en tests / Embedding / junto con un Makefile.win. Tal vez ese sea el comienzo más simple si estás dispuesto a aprender sobre R internals.
No creo que ninguno de los anteriores haya respondido a la pregunta, que fue evaluar 2 + 2;). Usar una expresión de cadena sería algo como:
#include <Rinternals.h>
#include <R_ext/Parse.h>
#include <Rembedded.h>
int main(int argc, char **argv) {
SEXP x;
ParseStatus status;
const char* expr = "2 + 2";
Rf_initEmbeddedR(argc, argv);
x = R_ParseVector(mkString(expr), 1, &status, R_NilValue);
if (TYPEOF(x) == EXPRSXP) { /* parse returns an expr vector, you want the first */
x = eval(VECTOR_ELT(x, 0), R_GlobalEnv);
PrintValue(x);
}
Rf_endEmbeddedR(0);
return 0;
}
Esto carece de comprobación de errores, obviamente, pero funciona:
Z:/>gcc -o e.exe e.c -IC:/PROGRA~1/R/R-213~1.0/include -LC:/PROGRA~1/R/R-213~1.0/bin/i386 -lR
Z:/>R CMD e.exe
[1] 4
(Para obtener los comandos adecuados para su R use R CMD SHLIB ec
que le proporciona los indicadores de compilación relevantes)
También puede construir la expresión a mano si es lo suficientemente simple, por ejemplo, para rnorm(10)
usaría
SEXP rnorm = install("rnorm");
SEXP x = eval(lang2(rnorm, ScalarInteger(10)), R_GlobalEnv);