Rcpp 将长度为 0 (NULL) 的向量传递给 cppfunction
Rcpp pass vector of length 0 (NULL) to cppfunction
我有一个 cppFunction
,输入向量 ints
,例如:
library(Rcpp)
cppFunction('double test2(NumericVector ints) {
return 42;
}')
如果传递长度至少为 1 的向量,则输出是正确的:
> test2(1)
[1] 42
> test2(1:10)
[1] 42
对于长度为 0 的输入,我得到:
> test2(c())
Error: not compatible with requested type
有什么方法可以将长度为 0 或更大的向量传递给我的函数吗? IE。我的预期输出是:
> test2_expectedoutput(c())
[1] 42
我知道我可以通过首先检查 R 并调用该函数的不同版本来在 R 中对此进行控制,但我想避免这种情况。我希望有一些简单的解决方案,因为如果我正确理解 NumericVector zero;
的作用,在 cpp 中我也可以有一个长度为 0 的 NumericVector
。我能找到的唯一相关问题是 this on how to return a NULL object from within a Rcpp function to R。
c()
调用产生 NULL
,它不是 numeric
向量。这会在调用 test2
时产生错误。您可以通过 numeric
:
构建长度为 0 的数值向量
#check what `c()` does
str(c())
# NULL
# now we try numeric(0)
test2(numeric(0))
#[1] 42
作为一个建议,我认为C
、Fortran
或C++
函数应该很少被直接调用;最好编写一个包装器来执行一些初步操作,例如类型转换等。类似于以下内容:
test2Wrapp<-function(x) test2(as.numeric(x))
test2Wrapp(c())
#[1] 42
#This has the benefit to not calling the internal routines in cases where conversion isn't possible
test2Wrapp(iris)
#Error: (list) object cannot be coerced to type 'double'
几个月前,我们添加了作为 Nullable<T>
传递的功能,这可能正是您在这里想要的。
这是一个简单的例子:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
bool checkNull(Nullable<NumericVector> x) {
if (x.isNotNull()) {
// do something
NumericVector xx(x);
Rcpp::Rcout << "Sum is " << sum(xx) << std::endl;
return true;
} else {
// do nothing
Rcpp::Rcout << "Nothing to see" << std::endl;
return false;
}
}
/*** R
checkNull(1:3)
checkNull(NULL)
*/
及其输出:
R> sourceCpp("/tmp/null.cpp")
R> checkNull(1:3)
Sum is 6
[1] TRUE
R> checkNull(NULL)
Nothing to see
[1] FALSE
R>
通过模板化,我们尊重预期的类型,但清楚地区分存在与不存在。
我有一个 cppFunction
,输入向量 ints
,例如:
library(Rcpp)
cppFunction('double test2(NumericVector ints) {
return 42;
}')
如果传递长度至少为 1 的向量,则输出是正确的:
> test2(1)
[1] 42
> test2(1:10)
[1] 42
对于长度为 0 的输入,我得到:
> test2(c())
Error: not compatible with requested type
有什么方法可以将长度为 0 或更大的向量传递给我的函数吗? IE。我的预期输出是:
> test2_expectedoutput(c())
[1] 42
我知道我可以通过首先检查 R 并调用该函数的不同版本来在 R 中对此进行控制,但我想避免这种情况。我希望有一些简单的解决方案,因为如果我正确理解 NumericVector zero;
的作用,在 cpp 中我也可以有一个长度为 0 的 NumericVector
。我能找到的唯一相关问题是 this on how to return a NULL object from within a Rcpp function to R。
c()
调用产生 NULL
,它不是 numeric
向量。这会在调用 test2
时产生错误。您可以通过 numeric
:
#check what `c()` does
str(c())
# NULL
# now we try numeric(0)
test2(numeric(0))
#[1] 42
作为一个建议,我认为C
、Fortran
或C++
函数应该很少被直接调用;最好编写一个包装器来执行一些初步操作,例如类型转换等。类似于以下内容:
test2Wrapp<-function(x) test2(as.numeric(x))
test2Wrapp(c())
#[1] 42
#This has the benefit to not calling the internal routines in cases where conversion isn't possible
test2Wrapp(iris)
#Error: (list) object cannot be coerced to type 'double'
几个月前,我们添加了作为 Nullable<T>
传递的功能,这可能正是您在这里想要的。
这是一个简单的例子:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
bool checkNull(Nullable<NumericVector> x) {
if (x.isNotNull()) {
// do something
NumericVector xx(x);
Rcpp::Rcout << "Sum is " << sum(xx) << std::endl;
return true;
} else {
// do nothing
Rcpp::Rcout << "Nothing to see" << std::endl;
return false;
}
}
/*** R
checkNull(1:3)
checkNull(NULL)
*/
及其输出:
R> sourceCpp("/tmp/null.cpp")
R> checkNull(1:3)
Sum is 6
[1] TRUE
R> checkNull(NULL)
Nothing to see
[1] FALSE
R>
通过模板化,我们尊重预期的类型,但清楚地区分存在与不存在。