Skip to content
Prev 3222 / 10988 Next

[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