R从C – 最简单的可能Helloworld

R启动R解释器的最简单的C函数是什么?传递一个小expression式(例如2 + 2),然后得出结果? 我试图在Windows上与MingW进行编译。

你想从C调用R?

请参阅Writing R Extensions手册中的第8.1节 。 你也应该看看“测试”目录(下载源代码包解压缩它,你将有测试目录)。 之前在R-Help上提出了类似的问题, 这里是一个例子 :

#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; /* ie 0 on success */ } 

R手册中的简单例子就是这样的:

  #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; } 

顺便提一句,你可能要考虑使用Rinside来代替:Dirk在项目主页上提供了一个很好的“hello world”示例 。

你有兴趣从R调用C,这是我的原始答案:

这不完全是“你好世界”,但这里有一些很好的资源:

  • Jay Emerson最近在纽约的useR小组发表了关于R包开发的演讲,他提供了一些从R内部使用C的非常好的例子。从第9页开始, 在他的网站上看看这篇讨论的论文 。相关的源代码在这里: http : //www.stat.yale.edu/~jay/Rmeetup/MyToolkitWithC/ 。
  • Gopi Goswami于2005年在哈佛任教: C-C ++ – R(统计学) 。 这包括广泛的例子和源代码。

干得好。 这是主要功能,但是你应该能够适应更通用的功能。 本示例从C调用和C字符串构建R表达式。 你在Windows上编译你自己,但我已经提供了在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); } 

编译步骤:

 $ 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 

我不认为上面的任何一个都回答了这个问题 – 这是评估2 + 2的问题)。 使用一个字符串表达式就像这样:

 #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; } 

这显然没有错误检查,但工作原理:

 Z:\>gcc -o e.exe ec -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 

(为了得到适当的命令为您的R使用R CMD SHLIB ec ,它给你相关的编译器标志)

如果它足够简单,你也可以手工构建表达式,例如,你可以使用rnorm(10)

 SEXP rnorm = install("rnorm"); SEXP x = eval(lang2(rnorm, ScalarInteger(10)), R_GlobalEnv); 

我认为你不能比内联包(它支持C,C ++和Fortran)做得更好:

 library(inline) fun <- cfunction(signature(x="ANY"), body='printf("Hello, world\\n"); return R_NilValue;') res <- fun(NULL) 

这将为您打印“Hello,World”。 而且你甚至不知道在何处/如何/何时调用编译器和链接器。 [R_NilValue是R的SEXP的NULL版本,这里使用的.Call()签名要求您返回一个SEXP – 请参阅您在此处不能真正避免的“编写R扩展”手册。 ]

然后,您将采取这样的代码,并包装在一个包。 我们在使用Rcpp单元测试(超过200个,现在计数)和一些例子的联机方面取得了巨大的成功。

哦,这个内联的例子可以在任何操作系统上运行。 即使Windoze提供您已安装R包建设工具链,在PATH等pp。

编辑:我误解了这个问题。 你所需要的基本上就是小资源前端(使用纯C)以及RInside类为C ++分解了什么。

杰夫和我从来没有把移植到Windoze的困扰,但是RInside在最近发布的版本中在那里工作。 所以你应该可以在构建食谱的时候进行探索 ,创建一个只有C的变种,这样你才能将表达式提供给嵌入式的R进程。 我怀疑你仍然想要像Rcpp这样的线索,否则它会变得乏味。

编辑2:正如Shane所提到的,在测试/嵌入/ R和Makefile.win中都有一些例子。 也许这是最简单的开始,如果你愿意学习R内部。