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

Yasir Suhail yusuhail at gmail.com
Sat Dec 24 00:16:36 CET 2011


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. 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.

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


More information about the Rcpp-devel mailing list