Rcpp 模块:手动 build/expose C++ 类 到 R
RcppModules: Manually build/expose C+ classes to R
目标是包装相当大的现有 C++ classes 集合,以便从 R 调用。第一种方法是手动定义 R 引用 类 并调用 "SEXP-wrapped"入口点 - 这工作正常,没问题。我目前正在评估的另一种方法是 RcppModules。我可以成功地将它与 R 中的玩具示例 一起使用 - 使用 Rcpp::SourceCPP
。但是手动执行此操作有麻烦。示例:
//---example.cpp
#include "Rcpp.h"
using namespace Rcpp;
class Example
{
public:
Example(){};
SEXP add(SEXP x_, SEXP y_) const
{
double x = as<double>(x_);
double y = as<double>(y_);
double res = x + y;
return wrap(res);
}
};
RCPP_MODULE(Example_Module) {
class_<Example>( "Example" )
.constructor()
.method( "add", &Example::add )
;
}
然后build/compile:
g++ "-I...\R\win-library\3.2\Rcpp\include" "-I...\R\R-3.2.2\include" -O0 -g3 -Wall -c -fmessage-length=0 -o example.o "..\example.cpp"
g++ -static-libgcc -static-libstdc++ -Wl,-Bstatic -lstdc++ -lpthread -Wl,-Bdynamic -lR -shared "-L...\R\R-3.2.2\bin\x64" -o example.dll example.o -lR
产生 example.dll
而没有 warnings/errors...
然后,按照Rcpp::SourceCPP
(带verbose = TRUE
)的命令,加载dll并填充环境:
`.example` <- dyn.load('example.dll')
library(Rcpp)
populate( Rcpp::Module("Example_Module",`.example`), environment() )
最后一次调用 populate
使 R 崩溃(在 RStudio 中)。
据我了解,除了二进制文件之外,Rcpp 还必须创建包含生成的 R class 的 R 代码,然后将其加载到环境中。有没有办法看到这段代码?
是否可以(是否合适)使用 R 外部的 RcppModules 来包装大量 C++ classes?
最后一个问题是,现有的 C++ 代码显然分为包含 class 声明的头文件和包含 class 方法实现的源文件。在这种情况下可以应用 RcppModules 吗? - 我看到的所有示例都在一个 cpp 文件中。
谢谢
感谢@nrussell 在这里与您进行了一些澄清。您最后的评论有几个更具体的问题,我将简要回答:
1) 是的,RCPP_MODULE
总是用在头文件中。查看 CRAN 上的各种示例包,并可能使用 r-pkg.org 进行搜索。
2) 是的。使用一个包。在此处查看数十个建议包的答案。不要用手做。不要手动编写 Makefile。使用一个包。
3) 没有固定答案。
环顾四周并研究Rich FitzJohn 的 RcppR6 明确地针对许多本地 类 的用例编写,其中 Rcpp 模块在加载时变得太慢。
我的几个包使用 Rcpp 模块,但这些都是相对较小的包。
如需进一步讨论,请订阅 rcpp-devel 列表并post。
目标是包装相当大的现有 C++ classes 集合,以便从 R 调用。第一种方法是手动定义 R 引用 类 并调用 "SEXP-wrapped"入口点 - 这工作正常,没问题。我目前正在评估的另一种方法是 RcppModules。我可以成功地将它与 R 中的玩具示例 一起使用 - 使用 Rcpp::SourceCPP
。但是手动执行此操作有麻烦。示例:
//---example.cpp
#include "Rcpp.h"
using namespace Rcpp;
class Example
{
public:
Example(){};
SEXP add(SEXP x_, SEXP y_) const
{
double x = as<double>(x_);
double y = as<double>(y_);
double res = x + y;
return wrap(res);
}
};
RCPP_MODULE(Example_Module) {
class_<Example>( "Example" )
.constructor()
.method( "add", &Example::add )
;
}
然后build/compile:
g++ "-I...\R\win-library\3.2\Rcpp\include" "-I...\R\R-3.2.2\include" -O0 -g3 -Wall -c -fmessage-length=0 -o example.o "..\example.cpp"
g++ -static-libgcc -static-libstdc++ -Wl,-Bstatic -lstdc++ -lpthread -Wl,-Bdynamic -lR -shared "-L...\R\R-3.2.2\bin\x64" -o example.dll example.o -lR
产生 example.dll
而没有 warnings/errors...
然后,按照Rcpp::SourceCPP
(带verbose = TRUE
)的命令,加载dll并填充环境:
`.example` <- dyn.load('example.dll')
library(Rcpp)
populate( Rcpp::Module("Example_Module",`.example`), environment() )
最后一次调用 populate
使 R 崩溃(在 RStudio 中)。
据我了解,除了二进制文件之外,Rcpp 还必须创建包含生成的 R class 的 R 代码,然后将其加载到环境中。有没有办法看到这段代码? 是否可以(是否合适)使用 R 外部的 RcppModules 来包装大量 C++ classes? 最后一个问题是,现有的 C++ 代码显然分为包含 class 声明的头文件和包含 class 方法实现的源文件。在这种情况下可以应用 RcppModules 吗? - 我看到的所有示例都在一个 cpp 文件中。
谢谢
感谢@nrussell 在这里与您进行了一些澄清。您最后的评论有几个更具体的问题,我将简要回答:
1) 是的,RCPP_MODULE
总是用在头文件中。查看 CRAN 上的各种示例包,并可能使用 r-pkg.org 进行搜索。
2) 是的。使用一个包。在此处查看数十个建议包的答案。不要用手做。不要手动编写 Makefile。使用一个包。
3) 没有固定答案。
环顾四周并研究Rich FitzJohn 的 RcppR6 明确地针对许多本地 类 的用例编写,其中 Rcpp 模块在加载时变得太慢。
我的几个包使用 Rcpp 模块,但这些都是相对较小的包。
如需进一步讨论,请订阅 rcpp-devel 列表并post。