r - 如何从另一个 Rccp 函数调用在 Rcpp 中创建的函数
问题描述
我想在函数 h_evap 中运行一个 Rcpp 函数 esat。两者都在一个通用的 .cpp 文件中,我在 Rstudio 中使用 sourceCPP 执行它。这是代码。esat 和 h_evap 都被创建并且 esat 工作正常。但是 h_evap 给了我输出
> esat(42)
[1] 256.7082
> h_evap(42)
Error in h_evap(42) :
Not compatible with requested type: [type=closure; target=double].
我怀疑问题出在我如何尝试从全局环境中访问 esat 但无法弄清楚如何调用 esat 来获取输出值而不是闭包。
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector esat(NumericVector Tk) {
NumericVector esat_out(Tk.size(), NAN);
for (size_t i=0; i<Tk.size(); i++) {
esat_out[i] = 6.1121 * Tk[i];
}
return esat_out;
}
// [[Rcpp::export]]
NumericVector h_evap(NumericVector Tk) {
Environment env = Environment::global_env();
NumericVector f_esat = env["esat"];
NumericVector h_evap_out(Tk.size(), NAN);
for (size_t i=0; i<Tk.size(); i++) {
h_evap_out[i] = (313.15 - Tk[i]);
h_evap_out[i] = h_evap_out[i] + f_esat(Tk[i]);
}
return h_evap_out;
}
/*** R
h_evap(42)
*/
另一种方法是使用 cppFunction。我已经尝试过了,但仍然得到这个 Rcpp 新手不清楚的错误。这是代码
library(Rcpp)
cppFunction('NumericVector esat(NumericVector Tk) {
NumericVector esat_out(Tk.size(), NAN);
for (size_t i=0; i<Tk.size(); i++) {
esat_out[i] = 6.1121 * Tk[i];
}
return esat_out;
}')
cppFunction('NumericVector h_evap(NumericVector Tk) {
NumericVector h_evap_out(Tk.size(), NAN);
for (size_t i=0; i<Tk.size(); i++) {
h_evap_out[i] = esat(Tk[i]);
}
return h_evap_out;
}')
esat 编译得很好。h_evap 返回一个错误消息我不清楚...
解决方案
稍微重写您的文件以避免通过中间 R 函数调用 C++,这(通常)是一个坏主意,并且几乎总是对性能产生不必要的沉重负担。
当您在同一个文件中定义了一个有效的 C++ 函数时,在使用它之前(这样您就不需要签名来声明它,例如头文件会为您做的)可以简单地调用它。
我还更改了循环索引变量以在编译期间消除一个警告,并且,当我这样做时,删除using namespace Rcpp;
并切换到具有命名空间的显式调用,这在更大的代码库中更加明确和“更安全”。
编辑:由于你的循环实际上对循环索引是不变的,我们可以将代码重写为矢量化调用,这样更短、更简单、更快、更容易推理。(当然,也可以从 R 完成......)
代码
#include <Rcpp.h>
// [[Rcpp::export]]
Rcpp::NumericVector esat(Rcpp::NumericVector Tk) {
Rcpp::NumericVector esat_out(Tk.size(), NAN);
for (R_xlen_t i=0; i<Tk.size(); i++) {
esat_out[i] = 6.1121 * Tk[i];
}
return esat_out;
}
// [[Rcpp::export]]
Rcpp::NumericVector h_evap(Rcpp::NumericVector Tk) {
Rcpp::NumericVector h_evap_out(Tk.size(), NAN);
Rcpp::NumericVector f_out = esat(Tk);
for (R_xlen_t i=0; i<Tk.size(); i++) {
h_evap_out[i] = (313.15 - Tk[i]);
h_evap_out[i] = h_evap_out[i] + f_out[i];
}
return h_evap_out;
}
// [[Rcpp::export]]
Rcpp::NumericVector esatV(Rcpp::NumericVector Tk) {
Rcpp::NumericVector esat_out = 6.1121 * Tk;
return esat_out;
}
// [[Rcpp::export]]
Rcpp::NumericVector h_evapV(Rcpp::NumericVector Tk) {
Rcpp::NumericVector f_out = esatV(Tk);
Rcpp::NumericVector h_evap_out = 313.15 - Tk + f_out;
return h_evap_out;
}
/*** R
esat(42)
h_evap(42)
esatV(42)
h_evapV(42)
*/
用法
> Rcpp::sourceCpp("~/git/stackoverflow/68605528/answer.cpp")
> esat(42)
[1] 256.708
> h_evap(42)
[1] 527.858
> esatV(42)
[1] 256.708
> h_evapV(42)
[1] 527.858
>
推荐阅读
- ios - 未调用委托函数
- javascript - 使用javascript单击突出显示的元素
- reactjs - 我无法在 Azure Linux 环境中仅部署 ReactJS 应用程序的构建文件夹
- python - Pandas Out of Bounds 时间戳解决方法
- python - Python - 重复任务
- rust - 重新借用嵌套的可变引用
- javascript - 使用 gaxios(或 axios)管道请求
- ruby-on-rails - 如何通过很少的选项从连接表中选择数据记录?
- php - 当电子邮件形式的表格中没有这样的行时,PHP会给出错误
- c# - 连接到 Oracle 失败 => .Net