2010-03-17 40 views
18

啓動R解釋器,傳遞一個小表達式(例如2 + 2)並獲得結果的最簡單C函數是什麼?我試圖在Windows上與MingW進行編譯。R來自C - 最簡單可能Helloworld

+0

對於哪種操作系統? – 2010-03-17 15:35:30

+0

好點...澄清。 – jsight 2010-03-17 15:39:30

回答

10

你想從C調用R?

看看section 8.1 in the Writing R Extensions手冊。您還應該查看「測試」目錄(下載源代碼包將其解壓縮,然後您將擁有測試目錄)。類似的問題以前問及R-幫助和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 */ 
} 

從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在項目主頁上提供a nice "hello world" example

在你感興趣的調用由R C,這裏是我原來的答覆:

這不正是「世界你好」,但這裏有一些很好的資源:

+0

非常感謝......我錯過了R init函數調用... oops。你(和其他人)的例子非常有幫助(太糟糕了,我也不能給予其他幾個人接受的答案...... :))。 – jsight 2010-03-17 21:20:41

4

我認爲你不能做多inline包(支持C,C++和Fortran)要好得多:

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

,它將打印 '你好,世界' 爲您服務。而且你甚至不知道編譯器和鏈接器在何處/如何/何時被調用。 [R_NilValue是R的NULL版SEXP,這裏使用的.Call()簽名要求您返回一個SEXP - 請參閱您在此處無法避免的'Writing R Extensions'手冊。 ]

然後,您將採取這樣的代碼並將其包裝在一個包中。我們使用 inline作爲 Rcpp單元測試(超過200,現在計數)和一些示例,取得了巨大成功。

哦,而這個inline的例子可以在任何操作系統上運行。即使Windoze只要你有安裝將R包構建工具鏈,在PATH等PP

編輯:我誤解了問題。你想要的基本上是littler前端所做的(使用純C)以及RInside類爲C++分解了什麼。

傑夫和我從來沒有把littler移植到Windoze上,但RInside確實在最近發佈的版本中工作過。因此,您應該可以在構建配方中找到並創建RInside的C-only變體,以便您可以將表達式提供給嵌入式R進程。我懷疑你仍然需要像Rcpp這樣的線索,否則它會變得乏味。

編輯2:而作爲沙恩提到,確有在R源的幾個例子在測試/嵌入/連同Makefile.win。也許這是最簡單的開始,如果你願意學習R內部知識。

+0

確實如此,但這就是C++ ......我寧願一個C示例。不過,Rcpp看起來很簡單。 – jsight 2010-03-17 15:57:40

+0

是的,我做了相應的編輯。內聯工作正常,但沒有Rcpp。但是一旦你真的想交換數據,即使你覺得C++比C更復雜,我也會去Rcpp。它不一定是。 – 2010-03-17 16:02:34

+0

這很有趣,但與我所尋找的相反。我有興趣從(可能是傳統的)C代碼中調用R,而不是反過來......如果原始問題不明確,我很抱歉。雖然這個信息也很有幫助。 :) – jsight 2010-03-17 16:35:00

9

你在這裏。這是主要功能,但您應該能夠將其調整爲更通用的功能。本示例從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 
+0

它可以在VS2008(MS編譯器)下編譯?什麼是論據? – Sergey 2012-05-31 05:22:32

7

我不認爲任何上述已回答這個問題 - 這是評估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 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 

(要獲得可以供大家使用R CMD SHLIB e.c它給你的有關正確的命令編譯器標誌)

您也可以構建用手錶達,如果它足夠簡單 - 例如,對於rnorm(10)你會用

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

它可以在Visual Studio(MS編譯器)下編譯嗎?什麼是參數? – Sergey 2012-05-31 05:24:18

+0

不,VC沒有官方支持,本地編譯器是MinGW。可能有方法將VC代碼與R結合起來(例如通過DLL),但不能保證工作。 – 2012-06-05 23:49:09

+0

我在Visual Studio(MS編譯器)下編譯了代碼:)。爲此,應該手動創建R.lib庫。 – Sergey 2012-06-28 18:13:05