如何从另一个 Rccp 函数调用在 Rcpp 中创建的函数
how to call a function created in Rcpp from another Rccp function
我想 运行 函数 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 returns 错误信息我不清楚...
通过对各种堆栈溢出 Qs 和 As 的一些明智的研究以及 Dirk 的一些关键提示,以下代码似乎可以满足我的要求。两个关键点 - 使用 Function 并将 esat 的输出写入 NumericVector 并将其读入 h_evap。我还在做一个包...
#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();
Function f_esat = env["esat"];
NumericVector h_evap_out(Tk.size(), NAN);
NumericVector f_out = f_esat(Tk);
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_out[i];
}
return h_evap_out;
}
/*** R
esat(42)
h_evap(42)
*/
稍微重写您的文件 以避免通过中间 R 函数调用 C++ 这(通常)是一个坏主意,而且几乎总是不必要的和重税性能。
正如您在同一个文件中定义一个有效的 C++ 函数并且在其使用之前(这样您就不需要签名将其声明为例如头文件即可)可以简单地调用它。
我还更改了循环索引变量以消除编译期间的一个警告,并且在我这样做的同时,删除了 using namespace Rcpp;
并切换到带有命名空间的显式调用,它更显式且有点 'safer' 来自更大代码库中的惊喜。
编辑: 因为你的循环实际上对循环索引是不变的,
我们可以将代码重写为 vectorized 调用,它更短、更简单、更快且更易于推理。 (当然,也可以从 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/Whosebug/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
>
我想 运行 函数 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 returns 错误信息我不清楚...
通过对各种堆栈溢出 Qs 和 As 的一些明智的研究以及 Dirk 的一些关键提示,以下代码似乎可以满足我的要求。两个关键点 - 使用 Function 并将 esat 的输出写入 NumericVector 并将其读入 h_evap。我还在做一个包...
#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();
Function f_esat = env["esat"];
NumericVector h_evap_out(Tk.size(), NAN);
NumericVector f_out = f_esat(Tk);
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_out[i];
}
return h_evap_out;
}
/*** R
esat(42)
h_evap(42)
*/
稍微重写您的文件 以避免通过中间 R 函数调用 C++ 这(通常)是一个坏主意,而且几乎总是不必要的和重税性能。
正如您在同一个文件中定义一个有效的 C++ 函数并且在其使用之前(这样您就不需要签名将其声明为例如头文件即可)可以简单地调用它。
我还更改了循环索引变量以消除编译期间的一个警告,并且在我这样做的同时,删除了 using namespace Rcpp;
并切换到带有命名空间的显式调用,它更显式且有点 'safer' 来自更大代码库中的惊喜。
编辑: 因为你的循环实际上对循环索引是不变的, 我们可以将代码重写为 vectorized 调用,它更短、更简单、更快且更易于推理。 (当然,也可以从 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/Whosebug/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
>