混合 Rcpp 模块和 Rcpp::export
Mixing Rcpp modules and Rcpp::export
我想公开一个 C++ class 和一个函数,该函数将 class 的对象作为 R 的参数。我必须遵循简化的示例。我使用
创建了一个包
Rscript -e 'Rcpp::Rcpp.package.skeleton("soq")'
并将以下代码放入soq_types.h
#include <RcppCommon.h>
#include <string>
class Echo {
private:
std::string message;
public:
Echo(std::string message) : message(message) {}
Echo(SEXP);
std::string get() { return message; }
};
#include <Rcpp.h>
using namespace Rcpp;
RCPP_MODULE(echo_module) {
class_<Echo>("Echo")
.constructor<std::string>()
.method("get", &Echo::get)
;
};
//// [[Rcpp::export]]
void shout(Echo e) {
Rcout << e.get() << "!" << std::endl;
}
请注意,最后一条评论有额外的斜杠,不会导致导出函数。当我现在 运行:
$> Rscript -e 'Rcpp::compileAttributes()'
$> R CMD INSTALL .
R> library(Rcpp)
R> suppressMessages(library(inline))
R> library(soq)
R> echo_module <- Module("echo_module", getDynLib("soq"))
R> Echo <- echo_module$Echo
R> e <- new(Echo, "Hello World")
R> print(e$get())
一切都很好。不幸的是,如果我启用 Rcpp::export
,执行 compileAttributes()
并重新安装,我得到:
** testing if installed package can be loaded from temporary location
Error: package or namespace load failed for ‘soq’ in dyn.load(file, DLLpath = DLLpath, ...):
unable to load shared object '/home/brj/R/x86_64-pc-linux-gnu-library/3.6/00LOCK-soq/00new/soq/libs/soq.so':
/home/brj/R/x86_64-pc-linux-gnu-library/3.6/00LOCK-soq/00new/soq/libs/soq.so: undefined symbol: _ZN4EchoC1EP7SEXPREC
Error: loading failed
Execution halted
ERROR: loading failed
我的问题是:如何让两者都起作用?
我在使用 R.3.6.3 并且
R> sessionInfo()
....
other attached packages:
[1] inline_0.3.15 Rcpp_1.0.4.6
....
附录
对于那些试图按照上面的示例进行操作的人:源文件的名称完全正确非常重要 <package_name>_types.h
。否则,自动生成的 RcppExports.cpp
将不会 #include
它,因此 Echo
class 将不会在那里定义。这将导致编译错误。
错误消息抱怨已声明但未定义 Echo(SEXP)
,这是为了扩展 Rcpp::as<>
。对于由 Rcpp 模块处理的 类,使用 RCPP_EXPOSED_*
宏更容易:
#include <Rcpp.h>
class Echo {
private:
std::string message;
public:
Echo(std::string message) : message(message) {}
std::string get() { return message; }
};
RCPP_EXPOSED_AS(Echo);
using namespace Rcpp;
RCPP_MODULE(echo_module) {
class_<Echo>("Echo")
.constructor<std::string>()
.method("get", &Echo::get)
;
};
// [[Rcpp::export]]
void shout(Echo e) {
Rcout << e.get() << "!" << std::endl;
}
/***R
e <- new(Echo, "Hello World")
print(e$get())
shout(e)
*/
输出:
> Rcpp::sourceCpp('62228538.cpp')
> e <- new(Echo, "Hello World")
> print(e$get())
[1] "Hello World"
> shout(e)
Hello World!
所有这些都不在包内,而是使用 Rcpp::sourceCpp
。不过,我希望它也能在一个包中工作。
我想公开一个 C++ class 和一个函数,该函数将 class 的对象作为 R 的参数。我必须遵循简化的示例。我使用
创建了一个包Rscript -e 'Rcpp::Rcpp.package.skeleton("soq")'
并将以下代码放入soq_types.h
#include <RcppCommon.h>
#include <string>
class Echo {
private:
std::string message;
public:
Echo(std::string message) : message(message) {}
Echo(SEXP);
std::string get() { return message; }
};
#include <Rcpp.h>
using namespace Rcpp;
RCPP_MODULE(echo_module) {
class_<Echo>("Echo")
.constructor<std::string>()
.method("get", &Echo::get)
;
};
//// [[Rcpp::export]]
void shout(Echo e) {
Rcout << e.get() << "!" << std::endl;
}
请注意,最后一条评论有额外的斜杠,不会导致导出函数。当我现在 运行:
$> Rscript -e 'Rcpp::compileAttributes()'
$> R CMD INSTALL .
R> library(Rcpp)
R> suppressMessages(library(inline))
R> library(soq)
R> echo_module <- Module("echo_module", getDynLib("soq"))
R> Echo <- echo_module$Echo
R> e <- new(Echo, "Hello World")
R> print(e$get())
一切都很好。不幸的是,如果我启用 Rcpp::export
,执行 compileAttributes()
并重新安装,我得到:
** testing if installed package can be loaded from temporary location
Error: package or namespace load failed for ‘soq’ in dyn.load(file, DLLpath = DLLpath, ...):
unable to load shared object '/home/brj/R/x86_64-pc-linux-gnu-library/3.6/00LOCK-soq/00new/soq/libs/soq.so':
/home/brj/R/x86_64-pc-linux-gnu-library/3.6/00LOCK-soq/00new/soq/libs/soq.so: undefined symbol: _ZN4EchoC1EP7SEXPREC
Error: loading failed
Execution halted
ERROR: loading failed
我的问题是:如何让两者都起作用?
我在使用 R.3.6.3 并且
R> sessionInfo()
....
other attached packages:
[1] inline_0.3.15 Rcpp_1.0.4.6
....
附录
对于那些试图按照上面的示例进行操作的人:源文件的名称完全正确非常重要 <package_name>_types.h
。否则,自动生成的 RcppExports.cpp
将不会 #include
它,因此 Echo
class 将不会在那里定义。这将导致编译错误。
错误消息抱怨已声明但未定义 Echo(SEXP)
,这是为了扩展 Rcpp::as<>
。对于由 Rcpp 模块处理的 类,使用 RCPP_EXPOSED_*
宏更容易:
#include <Rcpp.h>
class Echo {
private:
std::string message;
public:
Echo(std::string message) : message(message) {}
std::string get() { return message; }
};
RCPP_EXPOSED_AS(Echo);
using namespace Rcpp;
RCPP_MODULE(echo_module) {
class_<Echo>("Echo")
.constructor<std::string>()
.method("get", &Echo::get)
;
};
// [[Rcpp::export]]
void shout(Echo e) {
Rcout << e.get() << "!" << std::endl;
}
/***R
e <- new(Echo, "Hello World")
print(e$get())
shout(e)
*/
输出:
> Rcpp::sourceCpp('62228538.cpp')
> e <- new(Echo, "Hello World")
> print(e$get())
[1] "Hello World"
> shout(e)
Hello World!
所有这些都不在包内,而是使用 Rcpp::sourceCpp
。不过,我希望它也能在一个包中工作。