# Calling R from C

## Introduction

Calling an R function from C involves:

- Creating a special list of function name and arguments
- Optionally setting the argument names with `SET_TAG()`
- Calling `eval()`

Creating the special list for the call can be done using the helper methods `lang1()` to `lang6()`, or for R 4.4.1 or later `allocLang()` can provide more flexibility if needed.

## `lang1()` - Calling an R function with no arguments

`lang1()` is for assembling a call to an R function without specifying any arguments.

In this example `getwd()` is called from C using `lang1()`

    #include <R.h>
    #include <Rinternals.h>

    SEXP call_r_from_c_with_lang1(void) {

      SEXP my_call = PROTECT(lang1(
        PROTECT(Rf_install("getwd"))
      ));

      SEXP my_result = PROTECT(eval(my_call, R_GlobalEnv));

      UNPROTECT(3);
      return my_result;
    }

Click to show R code

    code = r"(
    #include <R.h>
    #include <Rinternals.h>

    SEXP call_r_from_c_with_lang1(void) {

      SEXP my_call = PROTECT(lang1(
        PROTECT(Rf_install("getwd"))
      ));

      SEXP my_result = PROTECT(eval(my_call, R_GlobalEnv));

      UNPROTECT(3);
      return my_result;
    }
    )"

    callme::compile(code)

    call_r_from_c_with_lang1()
    #> [1] "/private/var/folders/kq/h7dv19mj00947dthlyb5w2780000gn/T/Rtmp9tjFPt/Rbuild41a847919b5/callme/vignettes"

## `lang2()` - Calling an R function with a single unnamed argument

`lang2()` is for assembling a call to an R function and specifying a single argument.

In this example `abs(-1)` is called from C using `lang2()`

    #include <R.h>
    #include <Rinternals.h>

    SEXP call_r_from_c_with_lang2(void) {

      SEXP val = PROTECT(ScalarReal(-1));
      SEXP my_call = PROTECT(lang2(
        PROTECT(Rf_install("abs")),
        val
      ));

      SEXP my_result = PROTECT(eval(my_call, R_GlobalEnv));

      UNPROTECT(4);
      return my_result;
    }

Click to show R code

    code = r"(
    #include <R.h>
    #include <Rinternals.h>

    SEXP call_r_from_c_with_lang2(void) {

      SEXP val = PROTECT(ScalarReal(-1));
      SEXP my_call = PROTECT(lang2(
        PROTECT(Rf_install("abs")),
        val
      ));

      SEXP my_result = PROTECT(eval(my_call, R_GlobalEnv));

      UNPROTECT(4);
      return my_result;
    }
    )"

    callme::compile(code)

    call_r_from_c_with_lang2()
    #> [1] 1

## `lang2()` - Calling an R function with a single named argument

In this example `tempfile(fileext = ".txt")` is called from C using `lang2()`

    #include <R.h>
    #include <Rinternals.h>

    SEXP call_r_from_c_with_lang2_named(void) {

      // Assemble the function + argument with name
      SEXP val = PROTECT(mkString(".txt"));
      SEXP my_call = PROTECT(lang2(
        PROTECT(Rf_install("tempfile")),
        val
      ));

      // Set the argument name
      SEXP t = CDR(my_call);
      SET_TAG(t, Rf_install("fileext"));

      // Evaluate the call
      SEXP my_result = PROTECT(eval(my_call, R_GlobalEnv));

      UNPROTECT(4);
      return my_result;
    }

Click to show R code

    code = r"(
    #include <R.h>
    #include <Rinternals.h>

    SEXP call_r_from_c_with_lang2_named(void) {

      // Assemble the function + argument with name
      SEXP val = PROTECT(mkString(".txt"));
      SEXP my_call = PROTECT(lang2(
        PROTECT(Rf_install("tempfile")),
        val
      ));

      // Set the argument name
      SEXP t = CDR(my_call);
      SET_TAG(t, Rf_install("fileext"));

      // Evaluate the call
      SEXP my_result = PROTECT(eval(my_call, R_GlobalEnv));

      UNPROTECT(4);
      return my_result;
    }
    )"

    callme::compile(code)

    call_r_from_c_with_lang2_named()
    #> [1] "/var/folders/kq/h7dv19mj00947dthlyb5w2780000gn/T//RtmpzTwosz/file41d27bc04afb.txt"

## Using `allocLang()` (R >= 4.4.1 only)

The C code is equivalent to this R code:

    print(pi , digits = 3)

    #include <R.h>
    #include <Rinternals.h>

    SEXP call_print_from_c(SEXP value, SEXP digits) {
      // Allocate a new call object
      SEXP my_call = PROTECT(allocLang(3));

      // Manipulate a pointer to this call object to
      // fill in the arguments and set argument names
      SEXP t = my_call;
      SETCAR(t, install("print")); t = CDR(t);
      SETCAR(t,  value)          ; t = CDR(t);
      SETCAR(t, digits);
      SET_TAG(t, install("digits"));
      eval(my_call, R_GlobalEnv);

      UNPROTECT(1);
      return R_NilValue;
    }

Click to show R code

    code = r"(
    #include <R.h>
    #include <Rinternals.h>

    SEXP call_print_from_c(SEXP value, SEXP digits) {
      // Allocate a new call object
      SEXP my_call = PROTECT(allocLang(3));

      // Manipulate a pointer to this call object to
      // fill in the arguments and set argument names
      SEXP t = my_call;
      SETCAR(t, install("print")); t = CDR(t);
      SETCAR(t,  value)          ; t = CDR(t);
      SETCAR(t, digits);
      SET_TAG(t, install("digits"));
      eval(my_call, R_GlobalEnv);

      UNPROTECT(1);
      return R_NilValue;
    }
    )"

    callme::compile(code)

    call_print_from_c(pi, digits = 3)