I have a c++ class myClass which has a method foo(int x=0) and it has a parameter x with default value = 0. The c++ class could be exported to R by
RCPP_MODULE(my_module) {
class_< myClass >( "myClass" )
.constructor()
.method( "foo", &myClass::foo )
;
}
However, in R, I am not able to call myClass$foo without specifying the value of x.
I have to specify the value of x regardless the default value.
So my question is how to export Rcpp class method with default arguments. I tried to search it over the internet. The closest thing that I found was
using namespace Rcpp;
double norm( double x, double y ) { return sqrt( x*x + y*y );
}
RCPP_MODULE(mod_formals2) {
function("norm", &norm,
}
But it doesn't work in my case.
I had the same problem recently. After looking at the source file of rcpp handling the classes (~/R/x86_64-pc-linux-gnu-library/3.2/Rcpp/include/Rcpp/module/class.h in my setup) I don't think that it is currently possible.
The best workaround I came up with was to create a wrapper in R to handle the default arguments.
Here is a full example demonstrating how to do it. I defined a simple function that accepts 3 arguments and outputs their sum. The second and third arguments are optional and set by default to 10 and 100.
mwe.cpp
#include <Rcpp.h>
class MWE {
public:
int sum_them(int mandatory_arg,
int optional_arg1,
int optional_arg2)
{
return (mandatory_arg+optional_arg1+optional_arg2);
}
};
RCPP_MODULE(mod_mwe) {
Rcpp::class_<MWE>( "MWE" )
.constructor()
.method("sum_them", &MWE::sum_them)
;
}
mwe.R
require('Rcpp')
# source the C++ code
sourceCpp('mwe.cpp')
# create an instance of the class:
my_mwe = new(MWE)
# assign a wrapper with default arguments to the instance:
assign('sum_them_wrapper',
function(mandatory_arg,
optional_arg1=10,
optional_arg2=100) {
return(my_mwe$sum_them(mandatory_arg, optional_arg1, optional_arg2))
},
envir = my_mwe
)
This outputs the expected result:
> my_mwe$sum_them_wrapper(3, optional_arg2=500)
[1] 513
Related
I have a function in C that gets run from R via .Call and the boolean parameter always gets evaluated as true. Here's a minimal reproducible example:
library(inline)
dummy <- cfunction(signature(x = "bool"),
body = '
int val = x?0:1;
SEXP fake = allocVector(LGLSXP, 5);
SEXP ans = allocVector(LGLSXP, val);
if (val== 1) {
return fake;
}
return ans;
')
dummy(FALSE)
dummy(TRUE)
Both of these function calls return logical(0)
That doesn't sound right, but I also do not think your code goes about this in the right way. In the still-small, still-fairly new package tidyCpp I am collecting a few convenience definitions. One of its examples is basically exactly your problem:
#include <tidyCpp>
// We use Rcpp here because it has cppFunction() and sourceCpp().
// We do not use any Rcpp headers.
// [[Rcpp::depends(tidyCpp)]]
// [[Rcpp::export]]
bool isItLogical(SEXP x) {
return R::isLogical(x);
}
/*** R
isItLogical(TRUE)
isItLogical(FALSE)
isItLogical(42)
*/
When I sourceCpp() this (using Rcpp just for the convenience of building, no real Rcpp code here) I see
> Rcpp::sourceCpp("~/git/tidycpp/inst/snippets/defineExamples.cpp")
>
isItLogical(TRUE)
[1] TRUE
>
isItLogical(FALSE)
[1] TRUE
>
isItLogical(42)
[1] FALSE
>
If we change it from isLogical (answering: is the incoming variable a boolean or not) to asLogical to return the boolean value instead it becomes
> Rcpp::sourceCpp("~/git/stackoverflow/66575428/answer.cpp")
>
asLogical(TRUE)
[1] TRUE
>
asLogical(FALSE)
[1] FALSE
>
asLogical(42) # not zero so ...
[1] TRUE
>
New function below.
#include <tidyCpp>
// We use Rcpp here because it has cppFunction() and sourceCpp().
// We do not use any Rcpp headers.
// [[Rcpp::depends(tidyCpp)]]
// [[Rcpp::export]]
bool asLogical(SEXP x) {
return R::asLogical(x);
}
/*** R
asLogical(TRUE)
asLogical(FALSE)
asLogical(42) # not zero so ...
*/
Obviously, you do not have to use tidyCpp and can just look at its sources to pick the respective C functions of the R API, but I find the naming conventions there a little inconsistent hence this small packages as a little shim around it...
Use asLogical to convert function arguments (which are type SEXP, never bool) to bool:
SEXP dummy(SEXP x) {
int val = asLogical(x);
if (val) {
return allocVector(LGLSXP, 5);
}
return ScalarLogical(0);
}
(though I tend to agree with Dirk that Rcpp is almost always the way to go, unless is a peculiar aversion to it, especially as a first step from R to using compiled code with R).
I got a problem when I try module with inheritance class. Basiclly, I can't compile this part.
RCPP_MODULE(PACE){
using namespace Rcpp;
class_<FPCAreg>("FPCAreg")
.constructor<List, List, double, double, int, bool, bool>()
.field("n", &FPCAreg::n)
;
}
Here FPCAreg is a inheritance class based on FPCA class, and "n" is defined in FPCA. No matter I use ".field("n", &FPCAreg::n)" or ".field("n", &FPCA::n)". When I use ".field("n", &FPCAreg::n)", the error message is "no matching function for call to blablabla", and for ".field("n", &FPCA::n)", that's same but different class name. Is there any suggestion? Thanks.
You can only declare fields and methods from the actual class. However, what you can do is expose the base class and the derived class, and hint the inheritance between them in derives.
Here is an example:
#include <Rcpp.h>
using namespace Rcpp;
class Base {
public:
Base(double x_) : x(x_){}
double x;
} ;
class Derived : public Base {
public:
Derived(int y_) : Base(2.0), y(y_){}
int y ;
} ;
RCPP_MODULE(PACE){
class_<Base>("Base")
.constructor<double>()
.field("x", &Base::x)
;
class_<Derived>("Derived")
.derives<Base>("Base")
.constructor<int>()
.field("y", &Derived::y)
;
}
I get this then from R:
> obj <- new(Derived, 10L)
> obj$y
[1] 10
> obj$x
[1] 2
In R the possibility exists to have a function that creates another function, e.g.
create_ax2 <- function(a) {
ax2 <- function(x) {
y <- a * x^2
return(y)
}
return(ax2)
}
The result of which is
> fun <- create_ax2(3)
> fun(1)
[1] 3
> fun(2)
[1] 12
> fun(2.5)
[1] 18.75
I have such a complicated create function in R which take a couple of arguments, sets some of the constants used in the returned function, does some intermediary computations etc... But the result is a function that is way too slow. Hence I tried to translate the code to C++ to use it with Rcpp. However, I can't figure out a way to construct a function inside a C++ function and return it to be used in R.
This is what I have so far:
Rcpp::Function createax2Rcpp(int a) {
double ax2(double x) {
return(a * pow(x, 2));
};
return (ax2);
}
This gives me the error 'function definition is not allowed here', I am stuck about how to create the function.
EDIT: The question RcppArmadillo pass user-defined function comes close, but as far as I can tell, it only provides a way to pass a C++ function to R. It does not provide a way to initialise some values in the C++ function before it is passed to R.
Ok, as far as I understand, you want a function returning function with a closure, a.k.a. " the function defined in the closure 'remembers' the environment in which it was created."
In C++11 and up it is quite possible to define such function, along the lines
std::function<double(double)> createax2Rcpp(int a) {
auto ax2 = [a](double x) { return(double(a) * pow(x, 2)); };
return ax2;
}
What happens, the anonymous class and object with overloaded operator() will be created, it will capture the closure and moved out of the creator function. Return will be captured into instance of std::function with type erasure etc.
But! C/C++ function in R requires to be of a certain type, which is narrower (as an opposite to wider, you could capture narrow objects into wide one, but not vice versa).
Thus, I don't know how to make from std::function a proper R function, looks like it is impossible.
Perhaps, emulation of the closure like below might help
static int __a;
double ax2(double x) {
return(__a * pow(x, 2));
}
Rcpp::Function createax2Rcpp(int a) {
__a = a;
return (ax2);
}
I am trying to write a C++/Rcpp function that has an optional argument whos default needs to be a vector of length 1 with a value of 0. The following does not compile properly:
cppFunction("std::vector<int> test(std::vector<int> out = {0}) {
return out;
}")
I get the following error:
Error in cppFunction("std::vector test(std::vector out =
{1}) {\n return out;\n}") : No function definition found In
addition: Warning messages: 1: No function found for Rcpp::export
attribute at fileee5f629605d7.cpp:5 2: In sourceCpp(code = code, env
= env, rebuild = rebuild, showOutput = showOutput, : No Rcpp::export attributes or RCPP_MODULE declarations found in source
What is the right way to do this?
This answer was posted on the Rcpp issue tracker. This is the desired result that I wanted just not with std::vector.
cppFunction("IntegerVector test(IntegerVector out = IntegerVector::create(0)) {
return out;
}")
You could wrap the underlying C++ function in an R function that uses a default value:
#include <Rcpp.h>
#include <vector>
// [[Rcpp::plugins(cpp11)]]
// [[Rcpp::export]]
std::vector<int> cpp_test(const std::vector<int>& x)
{
return x;
}
/*** R
test <- function(X = c(0L))
{
cpp_test(X)
}
test()
test(c(1:5))
*/
which gives you
> Rcpp::sourceCpp('~/RcppFiles/cpp_test.cpp')
> test()
[1] 0
> test(c(1:5))
[1] 1 2 3 4 5
Currently the Rcpp package didn't support the exporting the default values. There are several packages to improve this (including Rcpp11), thought, I have a solution on Rcpp with RCPP_MODULES:
library("Rcpp")
cppFunction(plugins=c("cpp11"),'NumericVector test(std::vector<int> out) {
return wrap(out);
}
RCPP_MODULE(mod) {
function("test",&test,List::create( _["out"] = std::vector<int>({0})), "Simple description");
}', verbose=TRUE,rebuild=TRUE)
I change the return type, thought, it work even if you return std::vector<int>.
So, how this works: it just creates a documentation entry with the default value, third argument for RCPP_MODULES.
With just {0} my R crashes, so, it's necessary for me to put std::vector explicitly.
ALL,
Consider following code:
class CPlayer
{
public:
CPlayer(bool new) { m_new = new; };
bool IsNewPlayer() { return m_new; }
private:
bool m_new;
};
int main()
{
std::vector<CPlayer> players_pool;
players_pool.push_back( false );
players_pool.push_back( false );
players_pool.push_back( true );
players_pool.push_back( false );
}
Now what I'm looking for is to remove the players which has m_new as true.
Is it possible to do something like this:
players_pool.erase( std::remove( players_pool.begin(), players_pool.end(), players_pool.at().IsNewPlayer() ), players_pool.end() );
Now everywhere the examples given are for simple integers and not for the class objects.
Is there an easy way to perform such an operation?
And I need it to work in MSVC 2010 and XCode 4 with 10.6 SDK.
Note: The code given is a simplified version of the actual code I'm working on. Class CPlayer has a lot more fields than I put here but they are not relevant to this post.
Thank you.
P.S.: I found this but my question here is if it will work on OSX. My remover looks like this:
struct Remover : public std::binary_function<CPlayer,void,bool>
{
public:
bool operator()(const CPlayer &player) const
{
return player.IsNewPlayer();
}
};
Yes, it is possible. The standard library provides std::remove, which removes objects which are equal to some specified value (using the == operator), and it has std::remove_if, which, instead of a value, takes a function which is called on the object, and if it returns true, it indicates that the object should be removed. So simply write a function which defines the condition you want, and use that:
players_pool.erase( std::remove_if(
players_pool.begin(),
players_pool.end(),
[](const CPlayer& p){ return p.IsNewPlayer(); }),
players_pool.end() );
Note, I used a lambda for the function passed to remove_if. If your compiler doesn't support that yet, you can simply define the function separately, either as a function (with the signature bool func(const CPlayer&);, or a function object with an bool operator()(const CPlayer&)
Simply use std::remove_if and a lambda function as predicate:
players.erase( std::remove_if( players.begin() ,
players.end() ,
[](const Player& player) { return player.IsNewPlayer(); }
) );
Lambdas are supported by VC10 (VS2010 C++ compiler).
In XCode you are using Clang? It supports lambda expressions too.
On the other hand, if your compiler not supports C++11 lambdas, your functor is the correct way.