I want to create a package in R that uses cpp-code with the Rcpp package. In the cpp-code I need to use classes and member functions with named arguments.
After building the package, functions inside of Rcpp-modules seem to be ignoring named inputs and parse by position instead.
For example using the test package, as described below, I get the following output
# test the library
library(test)
# foo1 is a function outside of a module
foo1(a = "a", b = "b") # works as expected
#> a is a, b is b
foo1(b = "b", a = "a") # works as expected
#> a is a, b is b
# function within module "ABCMODULE"
foo2(a = "a", b = "b") # works as expected
#> a is a; b is b
foo2(b = "b", a = "a") # switches arguments <-------
#> a is b; b is a
abc <- new(ABC)
abc$foo3(a = "a", b = "b") # works as expected
#> a is a; b is b
abc$foo3(b = "b", a = "a") # switches arguments <-------
#> a is b; b is a
I have looked into the many Rcpp-vignettes but could find any solution to this. Have I overlooked something in the documents? Did I do a mistake somewhere? And how can I solve this or is this a feature/bug?
Edit
On a similar note, when I try to set default values, i.e., std::string b = "b" in all code (updated below), the Rcpp-module-versions do not work when trying to use the default value (foo1(a = "a") results in Error Expecting single string value and abc$foo3(a = "a") results in Error in ... could not find valid method)
test package
I have created the package with
Rcpp::Rcpp.package.skeleton("test", module = T)
then I added the two following files in test/
added src/foo1.cpp
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
void foo1(std::string a, std::string b = "b") {
Rprintf("a is %s, b is %s", a.c_str(), b.c_str());
}
added src/ABC.cpp
// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*-
#include <Rcpp.h>
void foo2(std::string a, std::string b = "b") {
Rprintf("a is %s; b is %s\n", a.c_str(), b.c_str());
}
class ABC {
public:
ABC() {}
void foo3(std::string a, std::string b = "b");
};
void ABC::foo3(std::string a, std::string b) {
Rprintf("a is %s; b is %s\n", a.c_str(), b.c_str());
}
RCPP_MODULE(ABCMODULE){
using namespace Rcpp ;
function("foo2" , &foo2 , "documentation for foo2");
// with formal arguments specification
class_<ABC>("ABC")
// expose the default constructor
.constructor()
.method("foo3", &ABC::foo3 , "documentation for foo3")
;
}
modified R/zzz.R
I added the following line to the bottom of the file
loadModule("ABCMODULE", TRUE)
Related
How can I get from C an object name used as a function argument? I
have sample code in C that gives me access to the name of the function
being called:
#include <Rinternals.h>
SEXP xname(SEXP x)
{
const char *fun_name = CHAR(PRINTNAME(CAR(x)));
x = CDR(x);
const char *arg_name = isNull(TAG(x)) ? "" : CHAR(PRINTNAME(TAG(x)));
Rprintf("fn_name: %s, arg_name: %s\n", fun_name, arg_name);
return R_NilValue;
}
and from R:
> xname <- function(...) invisible(.External("xname", ...))
> x1 = 123
> xname(x1)
fn_name: xname, var_name:
However, I am trying to find a way to access the object name. In the
documentation I found a solution for named args only:
> xname(arg = x1)
fn_name: xname, var_name: arg
And I'd like to find the C equivalent for substitute():
> substitute(x1)
x1
I tried substitute() from Rinternals.h, but it always returned a list with what above. Does anyone know how to do it? Maybe findVarInFrame()?
Best regards
I was wondering whether it is possible to make an infix function, e.g. A %o% B with Rcpp.
I know that this is possible using the inline package, but have yet been able to find a method for doing this when using sourceCpp().
I have made the following infix implementation of %o% / outer() when arguments are sure to be vectors using RcppEigen and inline:
`%op%` <- cxxfunction(signature(v1="NumericVector",
v2="NumericVector"),
plugin = "RcppEigen",
body = c("
NumericVector xx(v1);
NumericVector yy(v2);
const Eigen::Map<Eigen::VectorXd> x(as<Eigen::Map<Eigen::VectorXd> >(xx));
const Eigen::Map<Eigen::VectorXd> y(as<Eigen::Map<Eigen::VectorXd> >(yy));
Eigen::MatrixXd op = x * y.transpose();
return Rcpp::wrap(op);
"))
This can easily be implemented in to be imported using sourceCpp(), however not as an infix function.
My current attempt is as follows:
#include <Rcpp.h>
using namespace Rcpp;
#include <RcppEigen.h>
// [[Rcpp::depends(RcppEigen)]]
// [[Rcpp::export]]
NumericMatrix outerProd(NumericVector v1, NumericVector v2) {
NumericVector xx(v1);
NumericVector yy(v2);
const Eigen::Map<Eigen::VectorXd> x(as<Eigen::Map<Eigen::VectorXd> >(xx));
const Eigen::Map<Eigen::VectorXd> y(as<Eigen::Map<Eigen::VectorXd> >(yy));
Eigen::MatrixXd op = x * y.transpose();
return Rcpp::wrap(op);
}
So to summarize my question.. Is it possible to make an infix function available through sourceCpp?
Is it possible to make an infix function available through sourceCpp?
Yes.
As always, one should read the Rcpp vignettes!
In particular here, if you look in Section 1.6 of the Rcpp attributes vignette, you'd see you can modify the name of a function using the name parameter for Rcpp::export.
For example, we could do:
#include <Rcpp.h>
// [[Rcpp::export(name = `%+%`)]]
Rcpp::NumericVector add(Rcpp::NumericVector x, Rcpp::NumericVector y) {
return x + y;
}
/*** R
1:3 %+% 4:6
*/
Then we'd get:
Rcpp::sourceCpp("~/infix-test.cpp")
> 1:3 %+% 4:6
[1] 5 7 9
So, you still have to name C++ functions valid C++ names in the code, but you can export it to R through the name parameter of Rcpp::export without having to do anything further on the R side.
John Chambers states three principles on page four of the (highly recommended) "Extending R" book:
Everything that exists in R is an object.
Everything that happens in R is a function call.
Interfaces to other software are part of R.
So per point two, you can of course use sourceCpp() to create your a compiled function and hang that at any odd infix operator you like.
Code Example
library(Rcpp)
cppFunction("std::string cc(std::string a, std::string b) { return a+b; }")
`%+%` <- function(a,b) cc(a,b)
cc("Hello", "World")
"hello" %+% "world"
Output
R> library(Rcpp)
R> cppFunction("std::string cc(std::string a, std::string b) { return a+b; }")
R> `%+%` <- function(a,b) cc(a,b)
R>
R> cc("Hello", "World")
[1] "HelloWorld"
R>
R> "hello" %+% "world"
[1] "helloworld"
R>
Summary
Rcpp is really just one cog in the machinery.
Edit
It also works with your initial function, with some minor simplification. For
`%op%` <- cppFunction("Eigen::MatrixXd op(Eigen::VectorXd x, Eigen::VectorXd y) { Eigen::MatrixXd op = x * y.transpose(); return op; }", depends="RcppEigen")
as.numeric(1:3) %op% as.numeric(3:1)
we get
R> `%op%` <- cppFunction("Eigen::MatrixXd op(Eigen::VectorXd x, Eigen::VectorXd y) { Eigen::MatrixXd op = x * y.transpose(); return op; }", depends="RcppEigen")
R> as.numeric(1:3) %op% as.numeric(3:1)
[,1] [,2] [,3]
[1,] 3 2 1
[2,] 6 4 2
[3,] 9 6 3
R>
(modulo some line noise from the compiler).
I cannot find a way to add an S4 show method to the exported S4 class without using .onLoad. The Rcpp gallery example suggests "Rcpp_yourclassname" as the object name should be sufficient but in practise my package complains it cannot not find the class:
Loading RcppS4show
in method for ‘show’ with signature ‘"Rcpp_Num"’: no definition for class “Rcpp_Num”
One can easily reproduce this by using the Rcpp module package skeleton:
# R console:
Rcpp::Rcpp.package.skeleton("RcppS4show", path = "/tmp", module = TRUE)
# In /tmp/RcppS4show edit the file:
# R/zzz.R
# ... as described below.
setwd("/tmp/RcppS4show")
devtools::load_all()
Add this to the bottom of R/zzz.R:
setMethod("show", "Rcpp_Num", function(object) {
writeLines(paste("Num(x, y) =", object$x, object$y))
})
I can workaround this by wrapping the loadModule and setMethod functions in .onLoad:
.onLoad <- function(libname, pkgname) {
loadModule("NumEx", TRUE)
setMethod("show", "Rcpp_Num", function(object) {
writeLines(paste("Num(x, y) =", object$x, object$y))
})
}
Now I can see my show method works:
# R console:
new(Num)
#> Num(x, y) = 0 0
However both the module skeleton documentation and the Rcpp-modules vignette explain that .onLoad has been deprecated in favor of using loadModule().
Additionally, having to abuse .onLoad() causes devtools::check() to note that writeLines() from my show method is bad practise:
> checking R code for possible problems ... NOTE
File ‘RcppS4show/R/zzz.R’:
.onLoad calls:
writeLines(paste("Num(x, y) =", object$x, object$y))
Package startup functions should use ‘packageStartupMessage’ to
generate messages.
See section ‘Good practice’ in '?.onAttach'.
Is there any way to register S4 methods without using .onLoad?
Perhaps I'm missing something, but...
Why not just define the show method on the C++ side? (Perhaps this is what Dirk meant when he said "I simply define my Modules all at once").
After running
Rcpp::Rcpp.package.skeleton("RcppS4show", path = "/tmp", module = TRUE)
to create the package, I edited Num.cpp to the following
#include <Rcpp.h>
class Num { // simple class with two private variables
public: // which have a getter/setter and getter
Num() : x(0.0), y(0){} ;
double getX() { return x ; }
void setX(double value){ x = value ; }
int getY() { return y ; }
// Show method
void show() { Rcpp::Rcout << "Num(x, y) = " << x << " " << y << "\n"; }
private:
double x ;
int y ;
};
RCPP_MODULE(NumEx){
using namespace Rcpp ;
class_<Num>( "Num" )
.default_constructor()
// read and write property
.property( "x", &Num::getX, &Num::setX )
// read-only property
.property( "y", &Num::getY )
// show method
.method("show", &Num::show)
;
}
Then from R
setwd("/tmp/RcppS4show")
devtools::load_all()
new(Num)
# Num(x, y) = 0 0
devtools::check()
# Most of the output is omitted, but...
# Status: OK
#
# R CMD check results
# 0 errors | 0 warnings | 0 notes
showMethods("show")
# Function: show (package methods)
# Some output omitted...
# object="Rcpp_Num"
# More output omitted...
I have a cpp function which has an R function as one of its arguments like below:
void mycppfunction(SEXP x, Rcpp::Function func)
func can be a function, or it can be NULL. How can I implement this? If I do this:
void mycppfunction(SEXP x, Rcpp::Nullable<Rcpp::Function> func)
then, the line:
func(x)
gives me the error:
error: no match for call to ‘(Rcpp::Nullable<Rcpp::Function_Impl<Rcpp::PreserveStorage> >) (SEXP)’
On the other hand, if I just define mycppfunction as:
void mycppfunction(SEXP x, Rcpp::Function func)
then running the code with a NULL value for func results in a segfault: "memory not mapped".
Yes you can do this but I would advise that you are careful about verifying the compatibility of the function passed in and the argument. Here's a small example, with minimal defensive code to ensure that f is a valid function:
#include <Rcpp.h>
typedef Rcpp::Nullable<Rcpp::Function> nullable_t;
// [[Rcpp::export]]
SEXP null_fun(Rcpp::NumericVector x, nullable_t f = R_NilValue) {
if (f.isNotNull()) {
return Rcpp::as<Rcpp::Function>(f)(x);
}
return Rcpp::wrap((double)Rcpp::sum(x));
}
/*** R
null_fun(1:5)
#[1] 15
null_fun(1:5, mean)
#[1] 3
null_fun(1:5, min)
#[1] 1
null_fun(1:5, max)
#[1] 5
*/
Note that the use of SEXP as a return type and the Rcpp::wrap((double)...) was just to quiet the compiler in this specific example, and won't necessarily apply to your use case(s).
The title basically says it all.
If I do this ...
makeActiveBinding("x", function() runif(2), .GlobalEnv)
x
# [1] 0.7332872 0.4707796
x
# [1] 0.5500310 0.5013099
... is there then any way for me to examine x to learn what function it is linked to (and if not, why not)?
(In this case, I'd like to be able to learn that x was defined to be function() runif(2).)
With a bit of noodling around in envir.c, I can get this to work:
#include <Rcpp.h>
using namespace Rcpp ;
#define HASHSIZE(x) LENGTH(x)
#define HASHVALUE(x) TRUELENGTH(x)
// [[Rcpp::export]]
SEXP get_binding_fun( std::string name, Environment env){
SEXP symbol = Rf_install( name.c_str() );
SEXP tab = HASHTAB(env) ;
SEXP c = PRINTNAME(symbol);
// finding the hash code for the symbol
int hashcode = HASHVALUE(c) % HASHSIZE(tab);
// get the value there from the hash table
SEXP res = CAR( VECTOR_ELT(tab, hashcode ) ) ;
return res ;
}
Save this into a .cpp file, sourceCpp it and use it with this R code:
> makeActiveBinding("x", function() runif(2), .GlobalEnv)
> get_binding_fun("x", .GlobalEnv)
# function ()
# runif(2)