2010-03-17 5 views
18

R 해석기를 시작하고 작은 표현식 (예 : 2 + 2)을 전달하고 결과를 가져 오는 가장 간단한 C 함수는 무엇입니까? Windows에서 MingW로 컴파일하려고합니다.R from C - 가장 단순한 가능한 Helloworld

+0

어떤 운영 체제 용입니까? –

+0

좋은 지적 ... 명확하게. – jsight

답변

10

C에서 R을 호출 하시겠습니까?

section 8.1 in the Writing R Extensions 설명서를 참조하십시오. 또한 "tests"디렉토리를 조사해야합니다 (소스 패키지를 다운로드하면 테스트 디렉토리가 생성됩니다). 비슷한 질문 이전에 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를 호출 관심에서

, 여기에 내 원래의 대답 :

이 정확히에 "Hello World"이지만, 여기에 몇 가지 좋은 자원입니다 :

+0

많은 감사 ... 나는 R init 함수를 호출하지 못했습니다 ... 죄송합니다. 당신 (및 다른 사람들)의 예는 매우 도움이되었습니다 (나도 다른 사람들에게 인정 된 답변을 줄 수는 없습니다 ... :)). – jsight

4

나는 당신이 (C, C++ 및 포트란을 지원)을 inline 패키지보다 훨씬 더 잘 할 수 없다고 생각 :

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'설명서를 참조하십시오. ]

그런 코드를 가져 와서 패키지로 포장하십시오. Rcpp 단위 테스트 (200 개 이상, 지금 계산 중) 및 일부 예제의 경우 inline을 사용하여 큰 성공을 거두었습니다.

아, 그리고이 inline 예제는 모든 OS에서 작동합니다. 심지어 Windoze가 PATH에 설치 한 R 패키지 건물 툴 체인을 제공하는 등 쪽

편집 :. 내가 질문을 오해. 원하는 것은 원래 littler 프론트 엔드가 수행하는 작업 (순수 C 사용)과 RInside 클래스가 C++에 대해 분해 한 작업입니다.

제프와 나는 결코 최신 버전 인 RInside을 사용하여 Windoze에 littler을 이식하는 일에 전혀 신경을 쓰지 않았습니다. 따라서 빌드 레시피를 둘러보고 RInside의 C 전용 변형을 작성하여 표현식을 포함 된 R 프로세스에 공급할 수 있어야합니다. 나는 그것이 당신이 아직도 지루한 다른 것을 얻는 단서를 위해 Rcpp와 같은 것을 원한다고 생각한다.

편집 2 :을 그리고 셰인이 언급 한, R 소스의 몇 가지 예/임베딩/따라 Makefile.win와 시험에 실제로있다. 어쩌면 R 내부에 대해 배우려는 경우 가장 간단한 시작일 것입니다.

+0

사실,하지만 그건 C++입니다 ... 나는 지금 당장 C 예제를 원합니다. Rcpp는 사용하기 매우 간단 해 보입니다. – jsight

+0

예, 이에 따라 편집했습니다. 인라인은 Rcpp 없이는 잘 동작합니다. 하지만 일단 데이터를 교환하고 싶다면 C++이 C보다 복잡하다고 느낄지라도 Rcpp을 사용합니다. 꼭 그래야 할 필요는 없습니다. –

+0

그건 흥미 롭지 만 내가 찾고있는 것과는 반대입니다. 나는 (아마도 레거시) C 코드에서 R을 호출하는데 관심이 있는데, 그 반대가 아닌 ... 원래의 질문이 분명하지 않다면 유감이다. 이 정보도 유용합니다. :) – jsight

9

여기 있습니다. 그것은 주요 기능이지만 좀 더 일반적인 목적 기능에 맞게 조정할 수 있어야합니다. 이 예제는 C 호출과 C 문자열에서 R 표현식을 작성합니다. 당신은 창에 컴파일에 대한 자신에있어,하지만 난 리눅스에 컴파일 단계를 제공했습니다

/* 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 Compiler)에서 컴파일 할 수 있습니까? 논쟁은 무엇입니까? – Sergey

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 사용 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

+0

아니요, VC가 공식적으로 지원되지 않습니다. 네이티브 컴파일러는 MinGW입니다. VC 코드를 R과 결합하는 방법 (예 : DLL을 통해)이있을 수 있지만 작동하는 것은 아닙니다. –

+0

Visual Studio (MS Compiler)에서 코드를 컴파일했습니다. 이렇게하려면 R.lib 라이브러리를 수동으로 만들어야합니다. – Sergey