Rcpp Function Calling Another Rcpp Function

rcpp function calling another rcpp function

Just put both functions in the same .cpp file, or start working on a package.

If you stick to separate .cpp files, then F2 does not know about F1. You can call back F1 as an R function, but that's not going to be as efficient and you will have to deal with converting outputs to a double, etc ...

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
double F2(NumericVector a) {
double result=0;

// grab the R function F1
Function F1( "F1" ) ;
result = as<double>( F1(a) );

return result;
}

But really create a package or put all your functions in the same .cpp file.

how to call a function created in Rcpp from another Rccp function

A slight rewrite of your file to avoid calling a C++ via an intermediate R function which is (generally) a bad idea and almost always an uncalled-for and heavy tax on performance.

As you defined a valid C++ function in the same file and before its use (so that you don't need a signature to declare it as e.g. a header file would do for you) can simply call it.

I also changed the loop index variable to get rid of one warning during compilation, and, while I was at it, removed using namespace Rcpp; and switched to explicit calls with namespace which is more explicit and a little 'safer' from surprises in larger code bases.

Edit: And as your loops are in fact invariant to the loop index,
we can rewrite the code as vectorized calls whicg is shorter, simpler, faster, and easier to reason with. (And could, of course, be done from R too...)

Code

#include <Rcpp.h>

// [[Rcpp::export]]
Rcpp::NumericVector esat(Rcpp::NumericVector Tk) {
Rcpp::NumericVector esat_out(Tk.size(), NAN);
for (R_xlen_t i=0; i<Tk.size(); i++) {
esat_out[i] = 6.1121 * Tk[i];
}
return esat_out;
}

// [[Rcpp::export]]
Rcpp::NumericVector h_evap(Rcpp::NumericVector Tk) {
Rcpp::NumericVector h_evap_out(Tk.size(), NAN);
Rcpp::NumericVector f_out = esat(Tk);
for (R_xlen_t i=0; i<Tk.size(); i++) {
h_evap_out[i] = (313.15 - Tk[i]);
h_evap_out[i] = h_evap_out[i] + f_out[i];
}
return h_evap_out;
}

// [[Rcpp::export]]
Rcpp::NumericVector esatV(Rcpp::NumericVector Tk) {
Rcpp::NumericVector esat_out = 6.1121 * Tk;
return esat_out;
}

// [[Rcpp::export]]
Rcpp::NumericVector h_evapV(Rcpp::NumericVector Tk) {
Rcpp::NumericVector f_out = esatV(Tk);
Rcpp::NumericVector h_evap_out = 313.15 - Tk + f_out;
return h_evap_out;
}

/*** R
esat(42)
h_evap(42)
esatV(42)
h_evapV(42)
*/

Usage

> Rcpp::sourceCpp("~/git/stackoverflow/68605528/answer.cpp")

> esat(42)
[1] 256.708

> h_evap(42)
[1] 527.858

> esatV(42)
[1] 256.708

> h_evapV(42)
[1] 527.858
>

Calling a Rcpp function from another Rcpp function while building an R package

Two possible solutions:

The 'quick-and-dirty', solution -- include the function declaration in the file where you use it:

#include <Rcpp.h>
using namespace Rcpp;

// declare fun1
int fun1(int a1);

// [[Rcpp::export]]
Rcpp::NumericVector fun(Rcpp::NumericVector data1)
{
NumericVector fun_data = data1;
int n = data1.size();
for(i=0;i<n;i++){
fun_data[i] = fun1(fun_data[i]);
}
return(fun_data);
}

The more robust solution: write header files that declare the functions, which can then be #include-ed in each file. So you might have a header file fun1.h in the same src directory:

#ifndef PKG_FOO1_H
#define PKG_FOO1_H

int foo(int);

#endif

which you could then use with something like:

#include <Rcpp.h>
#include "fun1.h"
using namespace Rcpp;

// [[Rcpp::export]]
Rcpp::NumericVector fun(Rcpp::NumericVector data1)
{
NumericVector fun_data = data1;
int n = data1.size();
for(i=0;i<n;i++){
fun_data[i] = fun1(fun_data[i]);
}
return(fun_data);
}

As you progress, you're going to need to learn more C++ programming skills, so I recommend checking out one of the books here; in particular, Accelerated C++ is a great introduction.

Calling another cpp function in templated Rcpp function

The following approach to implementing apply_cpp_fun uses the trick of capturing the output type of the function to be applied using decltype and converting it to the appropriate SEXP type with Rcpp::traits::r_sexptype_traits<T>::rtype. If this is captured as a constexpr int then it can be used as the template parameter for creating an Rcpp:Vector of the appropriate type.

The upside of doing it this way is that you don't need to pass any template parameters to apply_cpp_fun.

#include <Rcpp.h>

template<typename Func, typename Input>
SEXP apply_cpp_fun(Input& v, Func f)
{
int n = v.size();
constexpr int t = Rcpp::traits::r_sexptype_traits<decltype(f(v, n))>::rtype;
Rcpp::Vector<t> result(n);

for (int i = 0; i < n; i++) result(i) = f(v, i);
return result;
}

Suppose we have the following functions to be applied:

#include <string>
#include <vector>
// [[Rcpp::plugins("cpp11")]]

Rcpp::String as_string(Rcpp::NumericVector const& x, int i) {
return std::to_string(x[i]);
}

double as_numeric(Rcpp::NumericVector const& x, int i) {
return x[i];
}

Then we can apply them using apply_cpp_fun and export to R like this:

// [[Rcpp::export]]
Rcpp::NumericVector test1_tmpl(Rcpp::NumericVector x)
{
return apply_cpp_fun(x, as_numeric);
}

// [[Rcpp::export]]
Rcpp::StringVector test2_tmpl(Rcpp::NumericVector x)
{
return apply_cpp_fun(x, as_string);
}

Now in R:

test1_tmpl(1:5)
# [1] 1 2 3 4 5

test2_tmpl(1:5)
# [1] "1.000000" "2.000000" "3.000000" "4.000000" "5.000000"

Note

Although the OP accepted my original answer of working with std:: types and simply passing them in and out using Rcpp's native conversions, it was pointed out by @KonradRudolph that this involves unnecessary copies. After some further clarifications and suggestions by the OP, I changed my answer to the above with the OP's permission, and have used the examples given in the OP's own answer.

Register C++ version of Rcpp function and use it within the other Rcpp function in a new package

This has been discussed before, and I would urge you to study these other questions and experiment with their answers.

Here you appear to have a cross-over from a C compilation (started by gcc) touching a file in which you crossed over to C++. Which, plainly stated, you cannot do for C compilation.

R offers C interfaces only. Rcpp helps you by autogenerating complying interface files. If you want to extend/alter them you have to play by the rules.

Wrapping C++ code in (simpler, more portable, cross-compiler, ...) C interfaces is a decades old trick. You likely find many resources for it.

Can we use Rcpp with multiple C++ functions?

Here is an example using an external cpp file.
The functions can interact inside the same file, but like others said you have to use header to use function from others files.
You have to use // [[Rcpp::export]] before any functions you want available in R.

(Credit to @F.Privé for improving the code)

1)
File cpp:

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
double sumC(NumericVector x) {
int n = x.size();
double total = 0;

for(int i = 0; i < n; ++i) {
total += x[i];
}
return total;
}

// [[Rcpp::export]]
double meanC(NumericVector x) {
return sumC(x) / x.size();
}

File R:

Rcpp::sourceCpp("your path/mean.cpp")
x <- 1:10
meanC(x)
sumC(x)

2)Alternative approach using cppfunction. You have to use includes argument

cppFunction('double meanC(NumericVector x) {
return sumC(x) / x.size();
}',includes='double sumC(NumericVector x) {
int n = x.size();
double total = 0;

for(int i = 0; i < n; ++i) {
total += x[i];
}
return total;
}')

Anyway I suggest you to use sourceCpp, using independent files result in much more maintainable and clean code

3)Using sourceCPP and multiple cpp files. You have to use headers file and do an header file for every file.cpp you want to use inside other cpp files.

sum.h file (ifndef prevent multiple definition)

#include <Rcpp.h>
#ifndef SUM1
#define SUM1

double sumC(Rcpp::NumericVector x);

#endif

sum.cpp (like before)

#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
double sumC(NumericVector x) {
int n = x.size();
double total = 0;

for(int i = 0; i < n; ++i) {
total += x[i];
}
return total;
}

mean.cpp file
(you have to include sum header) #include "sum.h"

#include <Rcpp.h>
#include "sum.h"
using namespace Rcpp;

// [[Rcpp::export]]
double meanC(NumericVector x) {
return sumC(x) / x.size();
}


Related Topics



Leave a reply



Submit