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.
Thanks in advance,
Chris
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.r-forge.r-project.org/pipermail/rcpp-devel/attachments/20110812/6ed90a35/attachment.htm>
[Rcpp-devel] integer arrays as arguments for a module function
7 messages · Chris DuBois, Dirk Eddelbuettel
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
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 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
-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.r-forge.r-project.org/pipermail/rcpp-devel/attachments/20110812/303d974c/attachment-0001.htm>
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
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>
On 13 August 2011 at 00:52, Chris DuBois wrote:
| 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?). Nice. | 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>&)? That is an odd issue with string. Not sure I've seen that before. | 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? I do not know -- maybe Romain has an idea? What I would do is to forgo std::transform and just do what the convert function does inside of a little worker loop. Which should compile. That said, we probably shouldn't have the error you triggered. Dirk | 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
|
|
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
On 13 August 2011 at 07:07, Dirk Eddelbuettel wrote:
| On 13 August 2011 at 00:52, Chris DuBois wrote:
| | 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?
|
| I do not know -- maybe Romain has an idea?
Got it. Gotta "love" C++ error messages. Upon staring at (hand-indented)
file7b8c8784.cpp:49:76: error: argument of type \
?char* (Foo::)(const std::string&)? does not match \
?char* (Foo::*)(const std::basic_string<char>&)?
for a bit longer, I realized that it is not the 'std::string' vs
'std::basic_string' issue, but rather the 'Foo::' vs 'Foo::*' !
Making convert() a free function is all that it takes:
edd at max:/tmp$ r chris.r
Loading required package: methods
std::string
std::vector<std::string>
char*
std::vector<char*>
edd at max:/tmp$
The file 'chris.r' is included below. Thanks for posting a self-contained
example -- 'mud-wrestling' these issues one by one is still the best way
forward.
There may be a way to do it with convert() as a member function though...
Dirk
-----------------------------------------------------------------------------
library(inline)
inc <- '
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
#include <cstring>
char *convert(const std::string & s) {
char *pc = new char[s.size()+1];
std::strcpy(pc, s.c_str());
return pc;
}
class Foo {
public:
Foo(IntegerVector tail) {
this->tail = tail;
}
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 ,"")
;
}
'
#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()
-----------------------------------------------------------------------------
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