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))
})

我可以通过将 loadModulesetMethod 函数包装在 .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...