[Rcpp-devel] integer arrays as arguments for a module function
I didn't find anything too relevant in the unit tests. I got a bit stuck, and asked a question on StackOverflow here: http://stackoverflow.com/questions/7048888/stdvectorstdstring-to-char-array . One answer seemed particularly promising (as shown by the working demo: http://ideone.com/U6QZ5 ). However, when I put this code into a module, I get an error: error: argument of type ?char* (Foo::)(const std::string&)? does not match ?char* (Foo::*)(const std::basic_string<char>&)? Here's the example I'm working with. Commenting out the std::transform and it compiles fine. Why does it work OK when not in a module, but fails when in a module? R code: inc <- paste(readLines('tests/convertCharExample.txt.cpp'),collapse="\n") fx <- cxxfunction( signature(), "" , include = inc, plugin = "Rcpp" ) a <- Module( "foo_mod", getDynLib(fx) ) b <- new(a$Foo,1:5) b$convertExample() convertCharExample.txt.cpp code: #include <iostream> #include <string> #include <vector> #include <algorithm> #include <iterator> #include <cstring> class Foo { public: Foo(IntegerVector tail) { this->tail = tail; } char *convert(const std::string & s) { char *pc = new char[s.size()+1]; std::strcpy(pc, s.c_str()); return pc; } int convertExample() { std::vector<std::string> vs; vs.push_back("std::string"); vs.push_back("std::vector<std::string>"); vs.push_back("char*"); vs.push_back("std::vector<char*>"); std::vector<char*> vc; std::transform(vs.begin(), vs.end(), std::back_inserter(vc), convert); for ( size_t i = 0 ; i < vc.size() ; i++ ) std::cout << vc[i] << std::endl; for ( size_t i = 0 ; i < vc.size() ; i++ ) delete [] vc[i]; return 0; } private: IntegerVector tail; }; RCPP_MODULE(foo_mod){ using namespace Rcpp ; class_<Foo>( "Foo" ) .constructor<IntegerVector>() .method( "convertExample", &Foo::convertExample ,"") ; }
On Fri, Aug 12, 2011 at 5:31 PM, Dirk Eddelbuettel <edd at debian.org> wrote:
On 12 August 2011 at 16:59, Chris DuBois wrote:
| Point taken: STL looks like the way to go in general.
|
| In my particular example, however, the arrays get immediately cast to
another
| structure foo (somebody else's code). So I need to cast from
IntegerVector to
| int[] before they get cast to foo[]. What you suggested works perfectly
(and
| makes sense in hindsight).
|
| Is the story identical for char[]? Where x is a CharacterVector, I
tried
|
| char* a = x.begin();
|
| and got
| error: cannot convert ?Rcpp::Vector<16>::iterator? to ?char*? in
| assignment
char can be a pain. It is something C and C++ didn't get quite right by
lacking a base type for string. Doing it in plain C (as in *argv[] from
main()) is a pain but doable.
CharacterVector works as the equivalent of std::vector< std::string >. Out
of
each element (ie string) you can extract the underlying char* but you may
have to rely on strcmp etc. Remember that you may be dealing with pointers
of pointers...
Have a peek at the unitTests/ directory to see if you find something.
Hope this helps, Dirk
| Any help much appreciated.
| Chris
|
| On Fri, Aug 12, 2011 at 3:19 PM, Dirk Eddelbuettel <edd at debian.org>
wrote:
|
|
| On 12 August 2011 at 14:50, Chris DuBois wrote:
| | Hi all,
| |
| | I'm trying to figure out how to pass in an array of integers to a
| function
| | inside a module. For example, adding the following function to
| runit.Module.R
| | works fine:
| |
| | int bla3( IntegerVector x ) {
| | return sum(x);
| | }
| |
| | However, I need to pass an int array, rather than an IntegerVector.
| Using int
| | x[] in the arguments doesn't compile (though I'm unfamiliar with
C++ in
| | general, so maybe this shouldn't work anyway).
| |
| | Alternatively, should I just cast x from an IntegerVector to an int
| array? I
| | tried various permutations of as, vector, <int>, etc, and would
like to
| learn
| | the proper way of doing this.
|
| You generally do not want old school x[] arrays in C++. Why? Because
STL
| vectors do _everything_ they do at (essentially) zero added cost,
free you
| from malloc/free and still allow you to access the straight memory
should
| you
| need to (to talk to a C API, say).
|
| So use IntegerVector for _the interface_. You can the, if you must,
do
|
| IntegerVector x;
|
| int a1[] = x.begin(); // STL-style iterator to beginning of
| memory
| int *a2 = x.begin(); // idem
|
| Hope this helps, Dirk
|
| --
| Two new Rcpp master classes for R and C++ integration scheduled for
| New York (Sep 24) and San Francisco (Oct 8), more details are at
| http://dirk.eddelbuettel.com/blog/2011/08/04#
| rcpp_classes_2011-09_and_2011-10
| http://www.revolutionanalytics.com/products/training/public/
| rcpp-master-class.php
|
|
--
Two new Rcpp master classes for R and C++ integration scheduled for
New York (Sep 24) and San Francisco (Oct 8), more details are at
http://dirk.eddelbuettel.com/blog/2011/08/04#rcpp_classes_2011-09_and_2011-10
http://www.revolutionanalytics.com/products/training/public/rcpp-master-class.php
-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.r-forge.r-project.org/pipermail/rcpp-devel/attachments/20110813/73ce0698/attachment.htm>