我在C中有一个函数,从R通过.Call
运行,布尔参数总是被评估为true
。下面是一个最小的可复制示例:
library(inline)
dummy <- cfunction(signature(x = "bool"),
body = '
int val = x?0:1;
SEXP fake = allocVector(LGLSXP, 5);
SEXP ans = allocVector(LGLSXP, val);
if (val== 1) {
return fake;
}
return ans;
')
dummy(FALSE)
dummy(TRUE)
这两个函数调用都返回logical(0)
这听起来不对,但我也不认为你的代码以正确的方式处理这个问题。在仍然很小、仍然相当新的包tidyCpp中,我收集了一些便利定义。其中一个例子基本上就是你的问题:
#include <tidyCpp>
// We use Rcpp here because it has cppFunction() and sourceCpp().
// We do not use any Rcpp headers.
// [[Rcpp::depends(tidyCpp)]]
// [[Rcpp::export]]
bool isItLogical(SEXP x) {
return R::isLogical(x);
}
/*** R
isItLogical(TRUE)
isItLogical(FALSE)
isItLogical(42)
*/
当我sourceCpp()
这(使用Rcpp
只是为了方便构建,没有真正的Rcpp
代码在这里),我看到
> Rcpp::sourceCpp("~/git/tidycpp/inst/snippets/defineExamples.cpp")
>
isItLogical(TRUE)
[1] TRUE
>
isItLogical(FALSE)
[1] TRUE
>
isItLogical(42)
[1] FALSE
>
如果我们将它从isLogical
(回答:传入变量是否为布尔值)更改为asLogical
以返回布尔值,而不是变成
> Rcpp::sourceCpp("~/git/stackoverflow/66575428/answer.cpp")
>
asLogical(TRUE)
[1] TRUE
>
asLogical(FALSE)
[1] FALSE
>
asLogical(42) # not zero so ...
[1] TRUE
>
新功能如下。
#include <tidyCpp>
// We use Rcpp here because it has cppFunction() and sourceCpp().
// We do not use any Rcpp headers.
// [[Rcpp::depends(tidyCpp)]]
// [[Rcpp::export]]
bool asLogical(SEXP x) {
return R::asLogical(x);
}
/*** R
asLogical(TRUE)
asLogical(FALSE)
asLogical(42) # not zero so ...
*/
显然,您不必使用tidyCpp
,只需查看其源代码即可选择R API的相应C函数,但我发现那里的命名约定有点不一致,因此这个小包在它周围有点模糊…
使用asLogical
将函数参数(类型为SEXP
,而非bool
)转换为bool:
SEXP dummy(SEXP x) {
int val = asLogical(x);
if (val) {
return allocVector(LGLSXP, 5);
}
return ScalarLogical(0);
}
(尽管我倾向于同意Dirk的观点,Rcpp几乎总是可行的,除非是对它的特殊厌恶,特别是作为从R到使用R编译代码的第一步)。