0

There is a discussion on Rccp-dev discussing how to convert from a string result to a RawVector (see https://lists.r-forge.r-project.org/pipermail/rcpp-devel/2010-October/001179.html).

// [[Rcpp::export]]
RawVector say_hello()
{
    std::string res = "hello friend";
    RawVector raw( res.size() ) ;
    std::copy( res.begin(), res.end(), raw.begin() ) ;
    return raw ;
}

It works as expected:

> Rcpp::sourceCpp( paste0(wd, "src/base64.cpp") );
> say_hello()
 [1] 68 65 6c 6c 6f 20 66 72 69 65 6e 64
> charToRaw("hello friend")
 [1] 68 65 6c 6c 6f 20 66 72 69 65 6e 64

Question: How to go the other direction in Rcpp?

If I have a RawVector how to transform it to a std::string? That is the equivalent of the rawToChar function within Rcpp?

> rawToChar ( charToRaw("hello friend") )
[1] "hello friend"

Clarification

Analogous to the above code with rawToChar and charToRaw, I want to have the following: print_hello(say_hello()) which should output "hello friend".

That is, I am trying to pass in a raw vector from R and have it convert the raw format to a std:string:

ONE FAILED attempt

// [[Rcpp::export]]
std::string print_hello(const RawVector& raw)
{   
    // https://stackoverflow.com/questions/8421250/convert-rcppcharactervector-to-stdstring
    std::string res = Rcpp::as<std::string>(raw);
    return res ;
}

ANOTHER FAILED ATTEMPT (THIS IS THE FORMAT I AM LOOKING FOR)

Here I included the Rccp serialize API: #include "RApiSerializeAPI.h"

#include "RApiSerializeAPI.h
std::string print_hello(const RawVector raw)
{   
    // https://github.com/eddelbuettel/rcppredis/blob/master/src/Redis.cpp
    std::string res = unserializeFromRaw(raw);
    return res ;
}

The errors are always similar:

base64.cpp:155:38: error: conversion from 'SEXP' {aka 'SEXPREC*'} to non-scalar type 'std::string' {aka 'std::__cxx11::basic_string<char>'} requested
  155 |  std::string res = unserializeFromRaw(raw);
  

A final try, also fails

std::string print_hello(SEXP s)
{   
    // https://github.com/eddelbuettel/rcppredis/blob/master/src/Redis.cpp
    Rcpp::RawVector raw = (TYPEOF(s) == RAWSXP) ? s : serializeToRaw(s);
    std::string res = unserializeFromRaw(raw);
    return res ;
}

There is a reference to a static_cast that I don't understand as well. The goal is: convert a RawVector to a std::string

I am swimming in deep waters here, just looking for a bit of guidance.

Windoze info

/*
g++ -std=gnu++11  -I"C:/PROGRA~1/R/R-42~1.1/include" -DNDEBUG   -I"C:/Users/......./AppData/Local/R/WIN-LI~1/4.2/Rcpp/include" -I"C:/_git_/github/......./src" -I"C:/_git_/github/......./inst/include"   -I"C:/rtools42/x86_64-w64-mingw32.static.posix/include"     -O2 -Wall  -mfpmath=sse -msse2 -mstackrealign  -c base64.cpp -o base64.o


R_RTOOLS42_PATH                             
C:\rtools42/x86_64-w64-mingw32.static.posix/bin;C:\rtools42/usr/bin

"pkg.version(Rcpp)"
[1] ‘1.0.9’


> R.version
               _                                
platform       x86_64-w64-mingw32               
arch           x86_64                           
os             mingw32                          
crt            ucrt                             
system         x86_64, mingw32                  
status                                          
major          4                                
minor          2.1                              
year           2022                             
month          06                               
day            23                               
svn rev        82513                            
language       R                                
version.string R version 4.2.1 (2022-06-23 ucrt)
nickname       Funny-Looking Kid  
*/

Dirk's answer

> r = (charToRaw("The quick brown fox"))
> r
 [1] 54 68 65 20 71 75 69 63 6b 20 62 72 6f 77 6e 20 66 6f 78
> r2c(r)
[1] "The quick brown fox"

> r2c(charToRaw("The quick brown fox"))
[1] "The quick brown fox\xd2\xce\002"

### BAFFLING ### Windoze!?<!?

> r <- charToRaw("The quick brown fox")
> r2c(r)
[1] "The quick brown fox\xdb\xce\002"
> r = (charToRaw("The quick brown fox"))
> r2c(r)
[1] "The quick brown fox"


Dharman
  • 30,962
  • 25
  • 85
  • 135
mshaffer
  • 959
  • 1
  • 9
  • 19
  • You may want to account for the fact that a post from 2010, or 12 years and heaven knows how many releases ago, may be the ultimate word on the topic. Raw to char conversion happen at the _C API of R_ level and not all functionality may map into Rcpp. – Dirk Eddelbuettel Sep 22 '22 at 22:54
  • I am reading some C code, just looking for an answer: ```// RAW() is not null-terminated // text = RAW(r_text); len = LENGTH(r_text); text = R_alloc(len+1, 1); text[len] = '\0'; memcpy(text, RAW(r_text), len);``` – mshaffer Sep 22 '22 at 22:56
  • ```mkString((char *) ans);``` – mshaffer Sep 22 '22 at 22:58
  • https://rcpp-devel.r-forge.r-project.narkive.com/joEUKvxE/convert-to-unsigned-char-variable – mshaffer Sep 22 '22 at 23:08
  • 1
    I think you may communicate more effectively in full sentences, and by showing edited code snippets in what is *your* main question. I honestly have no idea what links at snippets you are tossing around here in the last three comments, and sadly do not have the spare time to go digging. You may want to study my (not overly polished, but "years in production" and working -- running it here right now too) package RcppRedis which deals with both raw vectors and strings. – Dirk Eddelbuettel Sep 22 '22 at 23:44
  • Question: How to go the other direction in Rcpp? If I have a RawVector how to transform it to a std::string? – mshaffer Sep 23 '22 at 01:31
  • I downloaded the header file about 3 hours ago. https://github.com/eddelbuettel/rapiserialize/tree/master/inst/include ... I just don't know what to do with it. – mshaffer Sep 23 '22 at 01:35
  • I am a litte confused as to why you think _serialize_ and _unserialize_ have anything to do with the conversion. Serialization is a very different problem, it just happens to use raw vectors to transfer the payload. – Dirk Eddelbuettel Sep 23 '22 at 12:27
  • The data type in R is `raw` and it can be generated in 3 ways, from my understanding: (1) `as.raw(1:10)`, (2) `charToRaw` and (3) `serialize(iris,NULL)` ... The first two play nice with the `recasting` but the third one has NULL values so it doesn't seem to play nice. If I want to base64 encode `iris` using C++, how do I do that. If I stringify it with JSON it behaves as expected. I am trying to solve this THIRD use case. – mshaffer Sep 23 '22 at 12:32
  • If you need serialization, then unserialize is your answer and the the RApiSerialize package does what you want, You can study the two packages using it for how at the source level if you are confused ("I just don't know what to do with it."). If youe problem is char2raw and raw2char the actual R source code is in [this file](https://github.com/r-devel/r-svn/blob/master/src/main/raw.c). Good luck! – Dirk Eddelbuettel Sep 23 '22 at 12:49

1 Answers1

2

As hinted in the comments, the answer is hidden away in the RcppRedis package from which I just borrowed this actual one-liner (which I broke up onto three lines for nice display here):

> Rcpp::cppFunction("std::string r2c(RawVector x) { \
       const char *c = reinterpret_cast<char*>(x.begin()); \
       return std::string(c); }")
> r <- charToRaw("The quick brown fox")
> r
 [1] 54 68 65 20 71 75 69 63 6b 20 62 72 6f 77 6e 20 66 6f 78
> r2c(r)
[1] "The quick brown fox"
> 

We basically just ask C++ to 'view' the raw chars as standard chars. There is likely also a C function in R itself you could borrow. This worked for me, and apparently since at least 2014.

Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
  • ```> r = (charToRaw("The quick brown fox")) > r [1] 54 68 65 20 71 75 69 63 6b 20 62 72 6f 77 6e 20 66 6f 78 > r2c(r) [1] "The quick brown fox\xd9\xce\002" ``` – mshaffer Sep 23 '22 at 02:39
  • I think it is a WINDOZE console bug... varies the output from time to time. – mshaffer Sep 23 '22 at 03:51