[Rcpp-devel] A clean way to handle character/strings between R and Rcpp

Dirk Eddelbuettel edd at debian.org
Sat Apr 3 17:05:37 CEST 2021


On 3 April 2021 at 14:28, prezzemolo wrote:
| Hey.
| 
| I am wondering if there's some general guidance on what the 'right' options are to cleanly handle character arguments passed from R to Rcpp.
| 
| It is all rather simple: let's say I have a human-readable argument vector c("tree", "herb", "shrub") [It could also be a factor in R], which I can send to an Rcpp function along with other arguments for evaluation.
| What would be the cleanest way to define those arguments (plant types) in R to then have as little trouble sending them over to Rcpp for use in cases like if() statements?
| 
| 
| The use of enums comes to mind:
| 
| // beginningoffile
| enum class var_type { flower, tree };

That is a custom type you know / your C++ code knows. R and Rcpp have never
seen it --> extra work for you --> maybe simpler to do something else.

| RCPP_EXPOSED_ENUM_NODECL(var_type)
| 
| // [[Rcpp::export]]
| int charHandle1(var_type text_arg = var_type::flower) {

So don't do that.  Wrrite a 'mapper' function taking a std::string (or
Rcpp::CharacterVector or one of the equivalent ones, then map to your enum).

As the "fundamental theorem of software engineering" says "All problems in
computer science can be solved by another level of indirection" -- see for
example https://en.wikipedia.org/wiki/Indirection

|  if(text_arg == var_type::flower) {
|   Rcout << static_cast<int>(text_arg) << " says '0 (flower)'.\n";
|  } else if(text_arg == var_type::tree) {
|   Rcout << static_cast<int>(text_arg) << " says '1 (tree)'.\n";
|  }
|  return 0;
| }
| // endoffile
| 
| This however, doesn't seem to work. I understand R would have to know the var_type for it to work.
| Then I can do it simply by comparing the const char * argument. This will work, but the strcmp() comparison isn't very straightforward for someone who doesn't know C++ (and perhaps for some other reasons).

So make it const std::string text_arg = "flower" -- this lets you compare
via == (and loads of example packages do that.

-----------------------------------------------------------------------------
#include <Rcpp.h>

// [[Rcpp::export]]
void charHandle2(const std::string text_arg = "flower") {
    if (text_arg == "flower") {
        Rcpp::Rcout << text_arg << " says 'flower'.\n";
    } else if (text_arg == "tree") {
        Rcpp::Rcout << text_arg << " says 'tree'.\n";
    } else {
        Rcpp::Rcout << text_arg << " was incrompehensible.\n";
    }           
}

/*** R
charHandle2("flower")
charHandle2("tree")
charHandle2("banana")
*/
-----------------------------------------------------------------------------

That updated example yields:

> Rcpp::sourceCpp("/tmp/angelo.cpp")

> charHandle2("flower")
flower says 'flower'.

> charHandle2("tree")
tree says 'tree'.

> charHandle2("banana")
banana was incrompehensible.
> 

Hope this helps,  Dirk


| // [[Rcpp::export]]
| int charHandle2(const char* text_arg = "flower") {
|  if(strcmp(text_arg, "flower") == 0) {
|   Rcout << text_arg << " says 'flower'.\n";
|  } else if(strcmp(text_arg, "tree") == 0) {
|   Rcout << text_arg << " says 'tree'.\n";
|  }
|  return 0;
| }
| 
| I am looking for some good practice guidance on how to handle this safely and legibly to avoid sending people to function definitions. An argument could be made, for instance, that a list of plant type used as function arguments could be stored as factor in R and then sent and used in some way in Rcpp. What other options are there? To my best knowledge, support for enums is limited - I glanced over the vignettes and couldn't find any significant mention of enums (or factors, really), so I guess some other way of handling such cases should be taken. Has anyone dealt with such cases and has recommendations?
| 
| Regards,
| Angelo (Greetings from Genoa)
| _______________________________________________
| Rcpp-devel mailing list
| Rcpp-devel at lists.r-forge.r-project.org
| https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel
-- 
https://dirk.eddelbuettel.com | @eddelbuettel | edd at debian.org


More information about the Rcpp-devel mailing list