我在为Rcpp类编写R
通用打印机时遇到了一些问题。想想http://dirk.eddelbuettel.com/code/rcpp/Rcpp-modules.pdf第8页的统一示例。我试图定义这样的通用:
# Create new Uniform object:
uniform = Uniform$new(1, 2)
class(uniform)
## [1] "Rcpp_Uniform"
## attr(,"package")
## [1] "uniform"
# Printer for the object:
print.Rcpp_Uniform = function (x, ...) { message("Hi, I am an uniform object") }
现在,如果我只输入uniform
,我会:
C++ object <000000000d825c80> of class 'Uniform' <000000000287b090>
但这是我试图避免的。直接调用打印机可以提供我喜欢的内容:
print(uniform)
## Hi, I am an uniform object
有没有办法在不调用打印功能的情况下直接使用自定义打印机?
答案 0 :(得分:2)
感谢德克斯提示,我有一个解决方案。这是cpp文件uniform.cpp
,它包含统一类(复制了Dirks Rcpp Modules文档)和Rcpp模块定义:
// BEGIN uniform.cpp
#include <Rcpp.h>
using namespace Rcpp;
class Uniform {
public:
Uniform(double min_, double max_) : min(min_), max(max_) {}
NumericVector draw(int n) const {
RNGScope scope;
return runif( n, min, max );
}
double min, max;
};
double uniformRange( Uniform* w) {
return w->max - w->min;
}
RCPP_MODULE(unif_module) {
class_<Uniform>( "Uniform" )
.constructor<double,double>()
.field( "min", &Uniform::min )
.field( "max", &Uniform::max )
.method( "draw", &Uniform::draw )
.method( "range", &uniformRange )
;
}
// END uniform.cpp
现在可以获取并使用它:
library(Rcpp)
## Warning: package 'Rcpp' was built under R version 3.4.3
sourceCpp(file = "uniform.cpp")
uniform = Uniform$new(0, 10)
# Default printer:
uniform
## C++ object <00000000137a2e90> of class 'Uniform' <0000000015256dc0>
class(uniform)
## [1] "Rcpp_Uniform"
## attr(,"package")
## [1] ".GlobalEnv"
现在的线索是将方法show
定义为S4类Rcpp_Uniform
的自定义打印机。之后,打印机会执行所需的操作:
setMethod("show", class(uniform), function (object) {
cat("\n Hi, I am an uniform object!\n")
cat("\n I was initialized with a minimum value of", object$min)
cat("\n and a maximum value of ", object$max, ".\n", sep = "")
cat("\n Therefore my range is ", object$range(), ".", sep = "")
cat("\n\n")
})
## [1] "show"
uniform
##
## Hi, I am an uniform object!
##
## I was initialized with a minimum value of 0
## and a maximum value of 10.
##
## Therefore my range is 10.
要在将C++
类暴露给包中的R
后将该打印机作为默认打印机,只需创建R
文件(例如R/uniform_printer.R
)并放入其中的代码如下:
setMethod("show", "Rcpp_Uniform", function (object) {
cat("\n Hi, I am an uniform object!\n")
cat("\n I was initialized with a minimum value of", object$min)
cat("\n and a maximum value of ", object$max, ".\n", sep = "")
cat("\n Therefore my range is ", object$range(), ".", sep = "")
cat("\n\n")
})
请注意,有必要通过字符串(此处为Rcpp_Uniform
)明确引用该类。
这里的一个缺点是,这会在构建包时发出警告,因为在构建包时没有该类的定义。如果在获取cpp文件之前从上面运行setMethod
函数,则会发生相同的警告。
要避免此警告的一点是在setMethod
前面设置一个类。这看起来像这样:
setClass("Rcpp_Uniform")
setMethod("show", "Rcpp_Uniform", function (object) {
cat("\n Hi, I am an uniform object!\n")
cat("\n I was initialized with a minimum value of", object$min)
cat("\n and a maximum value of ", object$max, ".\n", sep = "")
cat("\n Therefore my range is ", object$range(), ".", sep = "")
cat("\n\n")
})
老实说,我不知道这是多么合适。但它在一个软件包中运行良好。