我使用的是Rcpp 0.12.11和R 3.4.0。
当我将Rcpp升级到0.12.11时,Rcpp :: compileAttributes自动生成的R文件RcppExports.R开始给我稍微不同的函数调用
run_graph_match <- function(A, B, algorithm_params) {
# Rcpp 0.12.10
.Call('RGraphM_run_graph_match', PACKAGE = 'RGraphM', A, B, algorithm_params)
# Rcpp 0.12.11
.Call(RGraphM_run_graph_match, A, B, algorithm_params)
}
有没有一种简单的方法来解释改变背后的原因?
后一种功能在检查R包时会导致错误。例如,错误如 符号&#39; RGraphM_run_graph_match&#39;不在命名空间中: .Call(RGraphM_run_graph_match,A,B,algorithm_params)
答案 0 :(得分:4)
恭喜,您已经体验过R 3.4.0中添加的Section 5.4: Registering native routines要求。该要求要求包含一个src/init.c
文件,该文件注册了每个 C ++ 函数及其参数。因此,Rcpp 0.12.11在RcppExports.cpp
内生成此文件。同时,RcppExports.R
文件是此问题的基础,其上下文取决于用户是否正确设置useDynLib(pkgname, .registration=TRUE)
或useDynLib(pkgname)
,其中后者不理想,因为它没有利用下面讨论的Rcpp 0.12.11中引入的新选项。
由于CRAN政策的这种转变,Rcpp 1 的属性创建者JJ Allaire受到启发,提出道格拉斯贝茨在2012年首次添加属性时提出的建议。具体来说,目标是将呼叫从基于字符串更改为符号。改变背后的基本原理简单地说,当包加载时,符号就会出现,而每次运行该函数时,该字符串必须被查找并转换为符号。因此,与过去基于字符串的Rcpp方法相比,重复调用时符号查找的成本更低。
基本上,这一行:
.Call('RGraphM_run_graph_match', PACKAGE = 'RGraphM', A, B, algorithm_params)
参与R在包含 R 函数的每次调用时查找符号,以访问 C ++ 函数。
同时,这一行:
.Call(RGraphM_run_graph_match, A, B, algorithm_params)
是对 C ++ 函数的直接调用,因为符号已经在内存中。
这些主要是为什么 Rcpp改变RcppExports.R
自动生成方式的原因。这种方法的缺点之一是无法像以前一样全局导出所有功能。特别是,某些用户在NAMESPACE
文件中有一个全局符号导出语句,例如
exportPattern("^[[:alpha:]]+")
必须删除它并选择手动指定应导出哪些函数或变量。
有关详细信息,您可能希望看到引入此功能的GitHub PR:
https://github.com/RcppCore/Rcpp/pull/694
1:有关属性的更多信息,请参阅我的历史记录帖子:http://thecoatlessprofessor.com/programming/rcpp/to-rcpp-attributes-and-beyond-from-inline/