4

I'm allocating an R vector using allocVector in a C function called with .Call from R. Is it possible to change the size/length of the vector after it has been allocated? I.e., similar to how realloc works in C.

In code, I'm looking for a function reallocVector so that the following to functions do the same thing.

SEXP my_function1(SEXP input){
    SEXP R_output = PROTECT(allocVector(REALSXP, 100));

    // Do some work on R_output

    // Keep only the first 50 items
    reallocVector(R_output, 50); 

    UNPROTECT(1);
    return R_output;
}

SEXP my_function1(SEXP input){
    SEXP tmp_output = PROTECT(allocVector(REALSXP, 100));

    // Do the same work on tmp_output

    // Keep only the first 50 items
    SEXP R_output = PROTECT(allocVector(REALSXP, 50));
    for (int i = 0; i < 50; ++i) {
        REAL(R_output)[i] = REAL(tmp_output)[i];
    }

    UNPROTECT(2);
    return R_output;
}
Fredrik Savje
  • 565
  • 2
  • 14
  • 1
    I think the closest to use is [`lengthgets`](https://github.com/wch/r-source/blob/trunk/src/main/builtin.c#L910) i.e. the API equivalent of `"length<-"` -- `return(lengthgets(tmp_output, 50));`. Else, you might consider `PROTECT_WITH_INDEX`/`REPROTECT` if you, only, need the new version of your vector and/or a `memcpy(REAL(R_output), REAL(tmp_output), sizeof(double) * 50);` – alexis_laz Mar 03 '17 at 09:19

1 Answers1

0

It seems that the SETLENGTH macro defined in the Rinternals.h header is the best choice to solve this. I.e.:

SEXP my_function1(SEXP input){
    SEXP R_output = PROTECT(allocVector(REALSXP, 100));

    // Do some work on R_output

    // Keep only the first 50 items
    SETLENGTH(R_output, 50);

    UNPROTECT(1);
    return R_output;
}
Fredrik Savje
  • 565
  • 2
  • 14