打印Rcpp类的通用

时间:2017-12-18 15:18:25

标签: r printing rcpp

我在为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

有没有办法在不调用打印功能的情况下直接使用自定义打印机?

1 个答案:

答案 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")
})

老实说,我不知道这是多么合适。但它在一个软件包中运行良好。