Rcpp 的 S4 方法生成的 S4 class 似乎仍然需要 .onLoad()
S4 method for Rcpp generated S4 class still seems to need .onLoad()
我找不到不使用 .onLoad
将 S4 show
方法添加到导出的 S4 class 的方法。 Rcpp gallery example 建议 "Rcpp_yourclassname" 因为对象名称应该足够了,但实际上我的包裹抱怨它找不到 class:
Loading RcppS4show
in method for ‘show’ with signature ‘"Rcpp_Num"’: no definition for class “Rcpp_Num”
可以使用 Rcpp 模块包骨架轻松重现:
# 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()
将此添加到 R/zzz.R
的底部:
setMethod("show", "Rcpp_Num", function(object) {
writeLines(paste("Num(x, y) =", object$x, object$y))
})
我可以通过将 loadModule
和 setMethod
函数包装在 .onLoad
:
中来解决这个问题
.onLoad <- function(libname, pkgname) {
loadModule("NumEx", TRUE)
setMethod("show", "Rcpp_Num", function(object) {
writeLines(paste("Num(x, y) =", object$x, object$y))
})
}
现在我可以看到我的显示方法有效了:
# R console:
new(Num)
#> Num(x, y) = 0 0
然而,模块框架文档和 Rcpp-modules vignette 都解释说 .onLoad
已被弃用,有利于使用 loadModule()
。
此外,不得不滥用 .onLoad()
导致 devtools::check()
注意到我的 show
方法中的 writeLines()
是不好的做法:
> 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'.
有什么方法可以不使用 .onLoad
来注册 S4 方法吗?
也许我遗漏了什么,但是...
为什么不直接在 C++ 端定义 show 方法? (也许这就是德克说 "I simply define my Modules all at once" 时的意思)。
运行
之后
Rcpp::Rcpp.package.skeleton("RcppS4show", path = "/tmp", module = TRUE)
为了创建包,我将 Num.cpp
编辑为以下内容
#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)
;
}
然后从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...
我找不到不使用 .onLoad
将 S4 show
方法添加到导出的 S4 class 的方法。 Rcpp gallery example 建议 "Rcpp_yourclassname" 因为对象名称应该足够了,但实际上我的包裹抱怨它找不到 class:
Loading RcppS4show
in method for ‘show’ with signature ‘"Rcpp_Num"’: no definition for class “Rcpp_Num”
可以使用 Rcpp 模块包骨架轻松重现:
# 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()
将此添加到 R/zzz.R
的底部:
setMethod("show", "Rcpp_Num", function(object) {
writeLines(paste("Num(x, y) =", object$x, object$y))
})
我可以通过将 loadModule
和 setMethod
函数包装在 .onLoad
:
.onLoad <- function(libname, pkgname) {
loadModule("NumEx", TRUE)
setMethod("show", "Rcpp_Num", function(object) {
writeLines(paste("Num(x, y) =", object$x, object$y))
})
}
现在我可以看到我的显示方法有效了:
# R console:
new(Num)
#> Num(x, y) = 0 0
然而,模块框架文档和 Rcpp-modules vignette 都解释说 .onLoad
已被弃用,有利于使用 loadModule()
。
此外,不得不滥用 .onLoad()
导致 devtools::check()
注意到我的 show
方法中的 writeLines()
是不好的做法:
> 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'.
有什么方法可以不使用 .onLoad
来注册 S4 方法吗?
也许我遗漏了什么,但是...
为什么不直接在 C++ 端定义 show 方法? (也许这就是德克说 "I simply define my Modules all at once" 时的意思)。
运行
之后Rcpp::Rcpp.package.skeleton("RcppS4show", path = "/tmp", module = TRUE)
为了创建包,我将 Num.cpp
编辑为以下内容
#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)
;
}
然后从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...