Hello,

The approach here is to use a callback to the new function of R, to mimic the call :

b <- new( B, 0L )

which you can do for example using the Language class:

namespace Rcpp {
    template <>
    SEXP wrap( const B& object ){
        Language call( "new", Symbol( "B" ), object.get_i() ) ;
        return call.eval() ;
    }
}

Now, for Rcpp classes to be aware of a custom wrap, you need some gymnatics, as described in the Rcpp-extending vignette. You need to include RcppCommon.h first, define you class and declare the custom wrap, then include Rcpp.h, then define you wrap.

I'm pasting a full pass at it below. Consider using the verbose = TRUE argument of cxxfunction to see what C++ code is being generated.

Things will get much simpler when we figure out a way to return classes exposed by modules and implement it.

Romain


require( inline )
require( Rcpp )

settings <- getPlugin("Rcpp")
settings$includes <- sprintf( "%s\n%s",
'
#include <RcppCommon.h>
// B just stores an integer i here
class B {
  public:
    B(int i) : i(i) {}

    int get_i() const {
      return i;
    }

  private:
    int i;
}  ;
namespace Rcpp{
    template <>
    SEXP wrap( const B& object ) ;
}
',
settings$includes
    )

inc <- '
namespace Rcpp {
    template <>
    SEXP wrap( const B& object ){
        Language call( "new", Symbol( "B" ), object.get_i() ) ;
        return call.eval() ;
    }
}

// A contains a vector v of pointers to B
class A {
  public:
    A(int n) : v(n) {}

    // THIS IS THE METHOD I WOULD LIKE TO IMPLEMENT:
    SEXP foo(int j) {
      if (!v[j]) {
        v[j] = new B(j);
      }

      // THIS DOES NOT WORK:
      return wrap(*v[j]);
    }

  private:
    std::vector<B*> v;
} ;

// Rcpp module exposing both A and B
RCPP_MODULE(MyModule) {
  class_<A>( "A" )
    .constructor<int>(
            "Create an instance of A with a given number of pointers")
    .method("foo",
            &A::foo,
            "(Create and) get one of the objects of type B.")
  ;

  class_<B>( "B" )
    .constructor<int>("Create an instance of B from an int.")
    .property("i",
              &B::get_i)
  ;
}
'

fx <- cxxfunction( , '

', includes = inc, settings = settings )
populate( Module( "MyModule", getDynLib( fx ) ), env = .GlobalEnv )

a <- new (A, 5)
b <- a$foo(0)
b$i







Le 18/04/11 16:12, schattenpfla...@arcor.de a écrit :
The way you try to implement it would require the class B to be
wrappable. You can have a look at the Rcpp-extending vignette for how to
enable wrap for custom classes.
The vignette states that I should specialize the wrap template or
implement the operator SEXP() for my class B. Unfortunately, it does not
give any hint about how to create an appropriate SEXP from an arbitrary
object pointer. After doing some research on the internet and a look at
the Matrix package I came up with the following approach. Could
something along these lines work at all?

#include <Rdefines.h>

SEXP foo() {
B* b = new B(1);
Rcpp::XPtr<B> xptr(b);
SEXP s4_obj = PROTECT(NEW_OBJECT(MAKE_CLASS("Rcpp_B")));
SEXP slot = Rcpp::wrap(std::string("pointer"));
SET_SLOT(s4_obj, slot, xptr);
UNPROTECT(1);

return s4_obj;
}

Unfortunately, this does not work as expected. In R, the returned
variable has type "S4", which is what I want. It cannot be used, though:
Error in get(".pointer", envir = env) : Object '.pointer' not found.
Perhaps all that is missing is a way to correctly initialize the
"pointer" or ".xData" of the created object. Any hints on that?

On the other hand, since I do not really understand in detail what
happens here, the code above could also be perfect nonsense...

Best regards,
Peter

--
Romain Francois
Professional R Enthusiast
+33(0) 6 28 91 30 30
http://romainfrancois.blog.free.fr
http://romain-francois.com
|- http://bit.ly/hdKhCy : Rcpp article in JSS
|- http://bit.ly/elZJRJ : Montpellier Comedie Club - Avril 2011
`- http://bit.ly/fhqbRC : Rcpp workshop in Chicago on April 28th


_______________________________________________
Rcpp-devel mailing list
Rcpp-devel@lists.r-forge.r-project.org
https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel

Reply via email to