[Rcpp-devel] c++ class as argument in rcpp function (using modules)

Yasir Suhail yusuhail at gmail.com
Fri Dec 23 03:18:11 CET 2011


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)
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.r-forge.r-project.org/pipermail/rcpp-devel/attachments/20111222/17d5c0b5/attachment.htm>


More information about the Rcpp-devel mailing list