Какова самая простая возможная функция C для запуска интерпретатора R, проходящая в маленьком выражении (например, 2 + 2) и выбирая результат? Я пытаюсь скомпилировать с MingW в Windows.
R из C - Простейший Возможный Helloworld
Ответ 1
Вы хотите вызвать R из C?
Посмотрите раздел 8.1 в руководстве Writing R Extensions. Вы также должны заглянуть в каталог "тесты" (загрузить исходный пакет, извлечь его, и у вас будет каталог тестов). Аналогичный вопрос ранее был задан в 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; /* 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 предоставляет хороший пример "привет мир" на главной странице проекта.
В вас интересует вызов C из R, вот мой оригинальный ответ:
Это не совсем "привет мир", но вот несколько хороших ресурсов:
- Недавно Джей Эмерсон рассказал о разработке пакета R в нью-йоркской группе useR, и он привел несколько очень хороших примеров использования C из R. Посмотрите документ из этого обсуждения на его веб-сайте, начиная со страницы 9. Все связанные исходные коды находятся здесь: http://www.stat.yale.edu/~jay/Rmeetup/MyToolkitWithC/.
- Курс, преподаваемый в Гарварде Гопи Госвами в 2005 году: C-С++ - R (в статистике). Это включает обширные примеры и исходный код.
Ответ 2
Здесь вы идете. Это основная функция, но вы должны уметь адаптировать ее к более универсальной функции. В этом примере создается выражение R из вызовов C, а также из строки C. Вы сами по себе для компиляции в 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
Ответ 3
Я не думаю, что какой-либо из вышеперечисленных вопросов ответил на вопрос, который должен был оценить 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);
Ответ 4
Я думаю, вы не можете сделать намного лучше, чем встроенный пакет (который поддерживает 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 NULL версия SEXP и используемая здесь подпись .Call()
требует, чтобы вы вернули SEXP - см. Руководство "Написание R-расширений", которого вы действительно не можете избежать здесь. ]
Затем вы берете такой код и завертываете его в пакет. У нас был большой успех при использовании встроенный для Rcpp модульные тесты (более 200 и считанные сейчас) и некоторые примеры.
О, и этот встроенный пример будет работать на любой ОС. Даже Windoze при условии, что у вас установлена цепочка инструментов R-пакета, в PATH и т.д.
Изменить: Я неправильно понял вопрос. То, что вам нужно, это то, что делает littler front-end (с использованием чистого C) и что RInside классы, учтенные для С++.
Джефф и я никогда не беспокоились о переносе littler в Windoze, но RInside работал там в самой последней версии. Таким образом, вы должны быть в состоянии выстукивать рецепты сборки и создавать C-единственный вариант RInside, чтобы вы может подавать выражение в внедренный процесс R. Я подозреваю, что вы все еще хотите что-то вроде Rcpp для подсказки, поскольку в противном случае это утомительно.
Изменить 2: И, как упоминает Шейн, действительно есть несколько примеров в источниках R в тестах/Вложение/вместе с Makefile.win. Возможно, это самый простой старт, если вы хотите узнать о внутренних функциях R.