[Rcpp-devel] c++ class as argument in rcpp function (using modules)
On 23 December 2011 at 18:16, Yasir Suhail wrote:
| Hi, | | I think I have figured out why we were getting the error. When we call the | function from R, the type of the instance passed is S4SXP, rather than | EXTPTRSXP, which is what XPtr(SEXP) expects. That's possible. | We can, however, use the Rcpp::S4 | (SEXP) constructor to get an S4 object. Are the user defined C++ classes | derived from Rcpp::S4 classes?? | | I don't know if there is still interest in this, so I don't know if I should | keep filling your inboxes. I think there is, but not everybody uses Rcpp modules all that actively so that you may have a limited audience. But extending Rcpp modules, and/or documenting it better, is definitely on the TODO list so you are on the right track. Dirk | Thanks! |
| On Thu, Dec 22, 2011 at 9:18 PM, Yasir Suhail <yusuhail at gmail.com> wrote:
|
| Hi,
|
| Dirk, thanks for uploading the next version, because it does sort of help
| here. The error now with Rcpp 0.9.8 is "expecting an external pointer" from
| XPtr on the following very toy example. It has something to do with the
| type of SEXP in the constructor, but I am not very familiar with the Rcpp
| internals to be able to figure it out.
|
| #include <Rcpp.h>
| class World {
| public:
| ? ? World() : msg("hello"){}
| ? ? World(const std::string s) : msg(s){}
| ? ? void set(std::string msg) { this->msg = msg; }
| ? ? std::string greet() const { return msg; }
| ? ? void addMsg(const World w2) {
| ? ? ? ? this->msg = this->msg + w2.greet();
| ? ? }
| ? ? World(SEXP x) {
| ? ? ? ? Rcpp::XPtr<World> ptr(x);
| ? ? ? ? msg = ptr->greet();
| ? ?}
| private:
| ? ? std::string msg;
| };
| RCPP_MODULE(yada){
| ? ? ? ? using namespace Rcpp ;
| ? ? ? ? class_<World>( "World" )
| ? ? ? ? ? ? .constructor()
| ? ? ? ? ? ? .constructor<std::string>()
| ? ? ? ? ? ? ? ? .method( "greet", &World::greet , "get the message"
| )
| ? ? ? ? ? ? ? ? .method( "set", &World::set ? ? , "set the
| message" )
| ? ? ? ? ? ? ? ? .method( "addMsg", &World::addMsg ?, "add the
| message from another object" );
| }
|
| And then in R:
|
| >library(yada)
| >a <- new(World,"this is a")
| >b <- new(World,"this is b")
| >a$addMsg(b)
| Error in a$addMsg(b) : expecting an external pointer
|
| I'd appreciate if someone could shed some light on it.
|
| Thanks!
|
| On Wed, Dec 21, 2011 at 7:52 PM, Yasir Suhail <yusuhail at gmail.com> wrote:
|
| Hi,
|
| Other than the approaches mentioned, I can also?specialize?an as
| <World>(SEXP) as
|
| ? ? ?template <>
| ? ? ?World as<World>(SEXP x) {
| Rcpp::XPtr<World> ptr(x);
| return World(ptr->greet());
| ? ? ?}
|
| However, this also gives segfault at runtime when addMsg is called. The
| final code, with alternative implementations commented out for
| experimentation is:
|
| #include <RcppCommon.h>
| #include <string>
| class World {
| public:
| ? ? World() : msg("hello"){}
| ? ? World(const std::string s) : msg(s){}
| ? ? void set(std::string msg) { this->msg = msg; }
| ? ? std::string greet() const { return msg; }
| ? ? void addMsg(const World w2) {
| this->msg = this->msg + w2.greet();
| ? ? }
| // ? ?World(SEXP x);
| /* ? ?World(SEXPREC* &w2) {
| msg = ((World*)w2)->greet();
| ? ? }
| */
| private:?
| ? ? std::string msg;
| };
| namespace Rcpp{
|
| template <> SEXP wrap(const World& object);
| template <> World as<World>(SEXP x);
| }
| #include <Rcpp.h>
|
|
| namespace Rcpp {
| ? ? ?template <>
| ? ? ?SEXP wrap( const World& object ){
| ? ? ? ? ?Language call( "new", Symbol( "World" ), object.greet() )
| ;
| ? ? ? ? ?return call.eval() ;
| ? ? ?}
| ? ? ?template <>
| ? ? ?World as<World>(SEXP x) {
| Rcpp::XPtr<World> ptr(x);
| return World(ptr->greet());
| ? ? ?}
| }
|
|
| /*World::World(SEXP x) {
| Rcpp::XPtr<World> ptr(x);
| msg = ptr->greet();
| }*/
|
| //...
|
| RCPP_MODULE(yada){
| using namespace Rcpp ;
| class_<World>( "World" )
| ?? ?// expose the default constructor
| ?? ?.constructor()
| ? ? ? ? ? ? .constructor<std::string>()
| ??? .method( "greet", &World::greet , "get the message" )
| .method( "set", &World::set ? ? , "set the message" )
| .method( "addMsg", &World::addMsg ?, "add the message from another
| object" );
| }
|
| Then, running with R -d gdb
| > a <- new(World,"hello ")
| > b <- new(World,"worlds")
| > a$greet( )
| [1] "hello "
| > a$addMsg( b)
|
| Program received signal EXC_BAD_ACCESS, Could not access memory.
| Reason: KERN_INVALID_ADDRESS at address: 0x0000000011000078
| 0x00000001042032df in std::basic_string<char, std::char_traits<char>,
| std::allocator<char> >::basic_string ()
| (gdb) bt
| #0 ?0x00000001042032df in std::basic_string<char, std::char_traits
| <char>, std::allocator<char> >::basic_string ()
| #1 ?0x0000000104358b18 in Rcpp::as<World> ()
| #2 ?0x000000010435d564 in Rcpp::CppMethod1<World, void,
| World>::operator() ()
| #3 ?0x000000010435eadb in Rcpp::class_<World>::invoke_void ()
| #4 ?0x0000000104164670 in CppMethod__invoke_void ()
| #5 ?0x00000001000928e9 in do_External ()
| #6 ?0x00000001000c4af7 in Rf_eval ()
| #7 ?0x00000001000c6d99 in do_begin ()
| #8 ?0x00000001000c48af in Rf_eval ()
| #9 ?0x00000001000c7cf3 in Rf_applyClosure ()
| #10 0x00000001000c4778 in Rf_eval ()
| #11 0x00000001000fed75 in Rf_ReplIteration ()
| #12 0x00000001000ff021 in R_ReplConsole ()
| #13 0x00000001000ff590 in run_Rmainloop ()
| #14 0x0000000100000e8b in main ()
| (gdb)?
|
| Thanks!
|
| On Wed, Dec 21, 2011 at 7:41 PM, Darren Cook <darren at dcook.org> wrote:
| | Hello Yasir, | Could you post your complete (minimal) code to the list. Then | someone | might be curious enough to try reproducing the problem. | | Darren | |
| On 2011-12-22 08:29, Yasir Suhail wrote:
| > Thanks Darren, Douglas, Richard, and Dirk!
| >
| > I can compile with the following definitions:
| >
| > World(SEXP x) {
| > Rcpp::XPtr<World> ptr(x);
| > msg = ptr->msg;
| > }
|
| > ...
|
|
| --
| Darren Cook, Software Researcher/Developer
|
| http://dcook.org/work/ (About me and my work)
| http://dcook.org/blogs.html (My blogs and articles)
|
|
|
|
|
|
|
| ----------------------------------------------------------------------
| _______________________________________________
| 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
"Outside of a dog, a book is a man's best friend. Inside of a dog, it is too dark to read." -- Groucho Marx