I'm currently learning to call compiled C code in R. Yesterday I created a function for the infinite pi series that when run in R returns a length 1 numeric vector (pi), which works great. Today I'm working on a function that outputs a variable length numeric vector, the Fibonacci sequence calculated for a user-defined n
.
In Writing R Extensions, it is noted that "the compiled code should not return anything, except through it's arguments". This is where I'm running into trouble. I don't know how to set up the following C code, namely the arguments in the final else
statement, so that no error is triggered following the call to system
.
I compiled a slightly different version in a C program and it works. However, the setup is different for compiling code that is to be called in R. I had to adjust it to accommodate the specifications for R function .C
.
How can I change the following function so that is compiles with no warnings or errors and can be called in R function .C
?
C code to be compiled:
void fibonacci(int *n, int *ans)
{
# *ans = 0; I tried this, didn't work
if(*n == 1 || *n == 2){
*ans = 1;
} else if(*n == 0){
*ans = 0;
} else {
*ans = fibonacci(n - 2) + fibonacci(n - 1); # tried 'ans' in arguments
} # here, didn't work
}
Error occurs here:
## compile and create shared library
> system('gcc -Wall -g -c -fPIC fibonacciR.c -o fibonacciR.o')
fibonacciR.c: In function ‘fibonacci’:
fibonacciR.c:8:5: error: too few arguments to function ‘fibonacci’
fibonacciR.c:1:6: note: declared here
fibonacciR.c:8:5: error: too few arguments to function ‘fibonacci’
fibonacciR.c:1:6: note: declared here
Changing the final ans
line in the C code to
} else {
*ans = fibonacci(n - 2, ans) + fibonacci(n - 1, ans);
}
produces a different error
> system('gcc -Wall -g -c -fPIC fibonacciR.c -o fibonacciR.o')
fibonacciR.c: In function ‘fibonacci’:
fibonacciR.c:10:5: error: void value not ignored as it ought to be
fibonacciR.c:10:5: error: void value not ignored as it ought to be
I'm definitely not an expert C programmer, and I do not know how to ignore an argument. Additionally, the way this function is set up, when I call it in R it will only return one value. So I presume I need to loop .C
for the user-defined argument n
. Is that correct?
Calls to follow, once I get the error sorted out.
system('gcc -Wall -g fibonacciR.o -shared -o libfibonacciR.so')
## load compiled program into R
dyn.load('libfibonacciR.so')
## create function to call compiled program
fibonacci <- function(n)
{
.C('fibonacci', as.integer(n), ans = as.integer(ans))$ans
}
## call function - result should be first 10 fibonacci numbers
fibonacci(n = 10)
## expected result
[1] 1 1 2 3 5 8 13 21 34 55
.C
interface, it is old and not recommended. Instead use.Call()
. Also maybe you don't know about the inline package? You might find adv-r.had.co.nz/C-interface.html helpful. – hadley