Integration of Fortran, C ++ with R
My task is to rewrite the R function in C ++ to speed up while loops. All R-codes were rewritten by Rcpp and Armadillo except .Fortran()
. I try to use Rinside first and it runs at a very slow speed as Dirk pointed out. (For data, you need to go through R -> C ++ -> R -> Fortran)
Since I don't want to rewrite Fortran codes in C ++ and vice versa, it's natural to speed up programs by linking C ++ directly to Fortran: R -> C ++ -> Fortran.
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
using namespace Rcpp;
extern "C"{
List f_(int *n,NumericMatrix a, NumericVector c, double* eps);
}
The problem is that I can integrate C ++ with Fortran and integrate R with C ++, but I cannot get these three things to work together!
I'm trying to compile C ++ on Linux but it just can't find RcppArmadillo.h
and namespace Rcpp
:
error: RcppArmadillo.h: No such file or directory
error: 'Rcpp' is not a namespace-name
When I sourceCpp("test.cpp")
call sourceCpp("test.cpp")
in R the console will display:
test.o:test.cpp:(.text+0x20b2): undefined reference to 'f_'
collect2: ld returned 1 exit status
Error in sourceCpp("test.cpp") : Error occurred building shared library.
I am also trying to combine all these things in a package
RcppArmadillo::RcppArmadillo.package.skeleton("TTTest")
But I don't know how to handle the package TTTest
(I believe it cannot be installed) after adding the files .cpp
and .f
in /src
and running compileAttributes
.
So, is it possible to do something like Rcpp? Or need to convert Fortran codes to C / C ++ codes?
Thank you for your help.
source to share
I would suggest that projects like this wrap your code into a package. I created a simple example of such a package, which I named mixedlang
which is available in this GitHub repo . I will describe the process of creating a package here.
I did the following steps:
- Set up the package structure from R with
RcppArmadillo::RcppArmadillo.package.skeleton("mixedlang")
(I used RcppArmadillo, not Rcpp as the OP was - nothing special about this Armadillo example) - Added the C ++ and Fortran files described below to the folder
src/
- In R run
Rcpp::compileAttributes("mixedlang/")
thendevtools::install("mixedlang/")
Code
I created a simple C ++ function whose sole purpose (essentially) was to call a Fortran function. The example function takes a numeric vector, multiplies each element by its index, and returns the result. Let's look at the Fortran code first:
fortranfunction.f90
This function simply takes two doubles and multiplies them, returning the result:
REAL*8 FUNCTION MULTIPLY (X, Y) REAL*8 X, Y MULTIPLY = X * Y RETURN END
test_function.cpp
Now we need to call this Fortran code from our C ++ code. In doing so, we need to consider a few things:
- Fortran arguments are passed by reference, not by value.
-
Since it is
MULTIPLY
defined in another file, we need to declare it in our C ++ file so that the compiler knows the arguments and return types.and. When declaring a Fortran function for our C ++ file, we will discard the case of the function name and add an underscore as the Fortran compiler should do this by default.
b. We must declare this function within
extern "C"
the communication specificationextern "C"
; C ++ compilers generally cannot use function names as unique identifiers as they allow overloading, but in order to call Fortran functions we need to do exactly what the communication specification doesextern "C"
(see, for example, this SO answer ).
#include "RcppArmadillo.h"
// [[Rcpp::depends(RcppArmadillo)]]
// First we'll declare the MULTIPLY Fortran function
// as multiply_ in an extern "C" linkage specification
// making sure to have the arguments passed as pointers.
extern "C" {
double multiply_(double *x, double *y);
}
// Now our C++ function
// [[Rcpp::export]]
Rcpp::NumericVector test_function(Rcpp::NumericVector x) {
// Get the size of the vector
int n = x.size();
// Create a new vector for our result
Rcpp::NumericVector result(n);
for ( int i = 0; i < n; ++i ) {
// And for each element of the vector,
// store as doubles the element and the index
double starting_value = x[i], multiplier = (double)i;
// Now we can call the Fortran function,
// being sure to pass the address of the variables
result[i] = multiply_(&starting_value, &multiplier);
}
return result;
}
Output example
After installing the package, I ran the example
mixedlang::test_function(0:9)
# [1] 0 1 4 9 16 25 36 49 64 81
Likely sources of original poster problems
- When trying to compile, initially they didn't let the compiler know where
RcppArmadillo.h
. - Trying to do it with
sourceCpp
justsourceCpp
trouble; it wasn't actually done to handle multiple files (see, for example, this answer from Dirk Eddelbuettel ), which is necessary when dealing with multiple languages.
I'm not sure what happened when they tried to flip it into a package, so I put together this example.
source to share