tags:

views:

103

answers:

2

There are lots of examples of sending integers to C++ from R, but none I can find of sending strings.

What I want to do is quite simple:

SEXP convolve(SEXP filename){

pfIn = fopen(filename, "r");

}

This gives me the following compiler error: loadFile.cpp:50: error: cannot convert 'SEXPREC*' to 'const char*' for argument '1' to 'FILE* fopen(const char*, const char*)'

So I need to convert filename to a const char*? Do I use CHAR?

+1  A: 

Here's a method that uses R internals:

#include <R.h>
#include <Rdefines.h>

SEXP convolve(SEXP filename){
  printf("Your string is %s\n",CHAR(STRING_ELT(filename,0)));
  return(filename);

}

compile with R CMD SHLIB foo.c, then dyn.load("foo.so"), and .Call("convolve","hello world")

Note it gets the first (0th) element of the SEXP passed in and takes the string elements and CHAR converts it. Mostly taken from the Writing R Extensions guide.

Barry

Spacedman
All true, and good to see an example for the R API -- but this ain't C++ which is what Chris asked for ;-) Easy to get there from what you posted though.
Dirk Eddelbuettel
Thanks Barry - amazing how a little commentary on the R Extensions guide - I've read it until my eyes bleed - helps. Works a treat.
Chris Wheadon
Does R know whether i'm writing C or C++? I hardly know myself! Help! Ah - Does the extern "C" { wrapper tell R I'm in C mode? I must admit I only added it because I couldn't get R to find my copiled code...
Chris Wheadon
extern "C" just tells the compiler not to give your function a C++ "mangled" name. If I compile a little function called 'bar' in foo.cpp then the symbol name ends up as "_Z3barv". Now you could call this in R, but how could you know what it's going to be? So you wrap it in extern "C" and it keeps its nice name.
Spacedman
Interesting. But how come I sometimes get away without using it? And it's rare to see it in the examples people use.
Chris Wheadon
If you compile with C compiler (cc -c foo.c; nm foo.o) you'll see sensible symbols, use C++ (c++ -c foo.c; nm foo.o) you'll see mangled names. These are Linuxy examples...
Spacedman
+4  A: 

Shane shows a good trick using environments, but Chris really asked about hot to send a string down from R to C++ as a parameter. So let's answer that using Rcpp and inline:

R> fun <- cxxfunction(signature(x="character"), plugin="Rcpp", body='
+    std::string s = as<std::string>(x);
+    return wrap(s+s);  // just to return something: concatenate it
+    ')
R> fun("abc")
[1] "abcabc"
R> 

That shows the templated helper as<T> (to get stuff from R) and the complement wrap() to return back to R. If you use Rcpp, that's all that there is to it.

Dirk Eddelbuettel