Using C in R package bool parameter is always true

Viewed 90

I have a function in C that gets run from R via .Call and the boolean parameter always gets evaluated as true. Here's a minimal reproducible example:

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)

Both of these function calls return logical(0)

2 Answers

That doesn't sound right, but I also do not think your code goes about this in the right way. In the still-small, still-fairly new package tidyCpp I am collecting a few convenience definitions. One of its examples is basically exactly your problem:

#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)
*/

When I sourceCpp() this (using Rcpp just for the convenience of building, no real Rcpp code here) I see

> Rcpp::sourceCpp("~/git/tidycpp/inst/snippets/defineExamples.cpp")

> 
isItLogical(TRUE)
[1] TRUE

> 
isItLogical(FALSE)
[1] TRUE

> 
isItLogical(42)
[1] FALSE
> 

If we change it from isLogical (answering: is the incoming variable a boolean or not) to asLogical to return the boolean value instead it becomes

> Rcpp::sourceCpp("~/git/stackoverflow/66575428/answer.cpp")

> 
asLogical(TRUE)
[1] TRUE

> 
asLogical(FALSE)
[1] FALSE

> 
asLogical(42) # not zero so ...
[1] TRUE
> 

New function below.

#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 ...
*/

Obviously, you do not have to use tidyCpp and can just look at its sources to pick the respective C functions of the R API, but I find the naming conventions there a little inconsistent hence this small packages as a little shim around it...

Use asLogical to convert function arguments (which are type SEXP, never bool) to bool:

SEXP dummy(SEXP x) {
  int val = asLogical(x);
  if (val) {
    return allocVector(LGLSXP, 5);
  }
  return ScalarLogical(0);
}

(though I tend to agree with Dirk that Rcpp is almost always the way to go, unless is a peculiar aversion to it, especially as a first step from R to using compiled code with R).

Related