Skip to content
Prev 38169 / 63424 Next

must .Call C functions return SEXP?

On Oct 27, 2010, at 7:43 PM, Andrew Piskorski wrote:

            
You are breaking the API = bad things happen.

.Call behaves like any function in R which means it takes arguments are returns a value. The result of .Call will be exactly the SEXP that you return from your C code hence you have to return something. It's quite common to R_NilValue which is NULL in R if you have nothing to do.
That's bad! All arguments are essentially read-only so you should never write into them! R has pass-by-value(!) semantics, so semantically you code has nothing to do with the result.1 and result.2 variables since only their *values* are guaranteed to be passed (possibly a copy). The fact that internally R attempts to avoid copying for performance reasons is the only reason why your code may have appeared to work, but it's invalid!

So what you really want to do is to have just

.Call("my_C_function", other.input)

and in your C code you have

SEXP result_1 = PROTECT(allocVector(VECSXP, 1e6));
SEXP result_2 = PROTECT(allocVector(VECSXP, 1e6));

/* do something ... */

and in order to pass it out you just create a list and return it:

SEXP result = PROTECT(allocVector(VECSXP, 2));
SET_VECTOR_ELT(result, 0, result_1);
SET_VECTOR_ELT(result, 1, result_2);
UNPROTECT(3);
return result;


Accordingly you get:
l = .Call("my_C_function", other.input)
result_1 = l[[1]]
result_2 = l[[2]]


Cheers,
Simon