Reputation: 1654
I am testing a call to a C function from R, using .C interface. The test consists in passing a numeric vector to the C function with no entries, dynamically allocates n positions, makes attributions and return the vector to R.
I'm using Calloc from R.h. The prototype of the function is
type* Calloc(size_t n, type)
as noted in Writing R Extensions.
The problem is that I don't get the new vector with the allocated positions in R. The vector continues to have no entries.
The code in R
fooR <- function(x) {
if (!is.numeric(x))
stop("argument x must be numeric")
out <- .C("foo",
x=as.double(x))
return(out$x)
}
x <- numeric()
result <- fooR(x)
The function in C
#include <R.h>
void foo(double *x)
{
int i, n;
n = 4;
x = Calloc(n, double);
for (i = 0; i < n; i++) {
x[i] = i;
printf("%f\n", x[i]); //just to check
}
}
The question is: Can .C inteface handle with such memory allocation?
Upvotes: 1
Views: 137
Reputation: 368399
Yes, you can use memory management that way but only if you use the .Call()
interface instead of the .C()
interface.
See the "Writing R Extensions" manual for Memory Allocation as well as Interface Functions.
There are other books, and a number of examples. I prefer C++ over C, and with Rcpp we can hide all the mechanics:
R> cppFunction('IntegerVector makeVec(int n) { return IntegerVector(n); }')
R> makeVec(2)
[1] 0 0
R> makeVec(4)
[1] 0 0 0 0
R>
This uses both .Call()
and R's memory allocation under the hood and is a quick little proof that "yes, you can" in fact create a vector dynamically.
Upvotes: 1
Reputation: 876
I don't know R language but I know C.
When you are taking a pointer to x
as an argument in function foo
then you can change content of x
inside foo
but not x
itself.
If you want to change an address of x
then you have to take "pointer to pointer to x" i.e. **x
.
In your implementation of foo
the compiler actually copy the value of *x
i.e. memory address to x
(compiler passes that address by value). So if you change the address inside the function then it remains unchanged at the outside.
Sorry, if I don't explain this clearly.
Anyway, in pure C the code should look like this:
void foo(double **x)
{
int i, n;
n = 4;
*x = (double*) calloc(n, sizeof(double));
for (i = 0; i < n; i++) {
(*x)[i] = i;
printf("%f\n", (*x)[i]); //just to check
}
}
And here is the working snippet: https://ideone.com/mRsdUH
Upvotes: 0