使用C在R包bool参数总是为真

  • 本文关键字:参数 bool 使用 r c
  • 更新时间 :
  • 英文 :


我在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编译代码的第一步)。

最新更新