Le 07/12/10 18:09, Douglas Bates a écrit :
I have created a small package available as
http://www.stat.wisc.edu/~bates/wrap_1..0.tar.gz that uses the
"non-intrusive" approach.

Attempts to compile produce
dtrMatrix.h:17: error: field ‘d_dat’ has incomplete type
dtrMatrix.h:18: error: field ‘d_dimnames’ has incomplete type
dtrMatrix.h: In member function ‘const Rcpp::NumericVector&
dtrMatrix::dat() const’:
dtrMatrix.h:24: error: ‘d_dat’ was not declared in this scope
dtrMatrix.h: In member function ‘const Rcpp::List&  dtrMatrix::dimnames() 
const’:
...

Apparently the forward declaration of the templated Vector class and
the typedef are unsuccessful.

I think we have been here before but did not resolve the issue.

Apparently we need to review the documentation.

The problem you have here is that you use the classes before they are defined (dtrMatrix has fields of type List, etc ...). It seems forward declaration does not give enough to the compiler.

Here is an approach. The main trick is to use the Rcppp::traits::is_convertible traits to ensure that conversion from dtrMatrix to SEXP si possible. This is used as part of the traits journey of wrap.


I also had to write this in two lines:

S4 s(x_) ;
dtrMatrix x(s) ;

Otherwise with your version:

dtrMatrix x( S4(x_) ) ;

The compiler believes that x is a function that takes an S4 and returns a dtrMatrix. If you have a copy of "Effective STL", this is explained in item 6 : "Be alert of C++ Most vexing parse".


As a sidenote, I don't have much experience with Matrix (the package, I have a bit of experience with the movie), but I understand that this means that Matrix objects are S4 objects. Any interest in moving them to C++ modules, so that the logic could be kept internal,etc ... Maybe for MatrixReloaded. One of the issues I would imagine is that Matrix is recommended so it cannot depend on Rcpp.

Romain


On Tue, Dec 7, 2010 at 10:35 AM, Romain Francois
<rom...@r-enthusiasts.com>  wrote:
Yes. One cheap way to deal with this is:

settings<- getPlugin( "Rcpp" )
settings$includes<- ..
cxxfunction( .., settings = settings )

I'm looking at the rest of the first email now.

Romain

Le 07/12/10 17:32, Douglas Bates a écrit :

On looking more closely I can't use cxxfunction with plugin="Rcpp" to
test this because the plugin inserts

#include<Rcpp.h>

before the user includes and some parts in the user includes need to
be declared before Rcpp.h is included.  I'll create a small package.

On Tue, Dec 7, 2010 at 10:06 AM, Douglas Bates<ba...@stat.wisc.edu>
  wrote:

I'm again trying to define instances of the wrap template for C++
classes that have data members defined in Rcpp.h

A stand-alone example, which is rather lengthy, is enclosed.  In this
example I am unsuccessful in using the "intrusive" formulation
described in the "Extending Rcpp" vignette.  I will try again with the
"non-intrusive" formulation.  Other suggestions are welcome.

library(Matrix)
library(inline)
library(Rcpp)

incl<- '
#include<RcppCommon.h>

namespace Rcpp {
     template<int RTYPE>    class Vector;
     template<int RTYPE>    class Matrix;
     class S4;
     typedef Vector<REALSXP>    NumericVector;
     typedef Vector<INTSXP>      IntegerVector;
     typedef Vector<VECSXP>      List;
     typedef Matrix<REALSXP>    NumericMatrix;
}

class dtrMatrix {
protected:
    Rcpp::NumericVector d_dat;
    Rcpp::List d_dimnames;
    int d_size;                 // must be square
    bool d_upper;               // true if upper triangular
    bool d_unit;                // true if unit diagonal
public:
    dtrMatrix(Rcpp::S4&) throw (std::runtime_error);
    operator SEXP();
};

#include<Rcpp.h>

dtrMatrix::dtrMatrix(Rcpp::S4&    xp) throw (std::runtime_error)
    : d_dat(xp.slot("x")), d_dimnames(xp.slot("Dimnames")) {
    if (!xp.inherits("dtrMatrix"))
        throw std::runtime_error("constructor needs S4 class dtrMatrix");
    IntegerVector dd = xp.slot("Dim");
    if (dd.size() != 2 || dd[0] != dd[1])
        throw std::runtime_error("Matrix must be square");
    d_size = dd[0];
    std::string uplo = as<std::string>(xp.slot("uplo"));
    d_upper = (uplo == "U") || (uplo == "u");
    std::string diag = as<std::string>(xp.slot("diag"));
    d_unit = (diag == "U") || (diag == "u");
}

dtrMatrix::operator SEXP() {
    Rcpp::S4 ans("dtrMatrix");
    ans.slot("x") = clone(d_dat);
    ans.slot("Dimnames") = clone(d_dimnames);
    IntegerVector dd(2);
    dd[0] = dd[1] = d_size;
    ans.slot("Dim") = dd;
    ans.slot("uplo") = d_upper ? "U" : "L";
    ans.slot("diag") = d_unit ? "U" : "N";
    return ans;
}
'

code<- '
dtrMatrix x(S4(x_));
return wrap(x);
'
ff<- cxxfunction(signature(x_ = "ANY"), code, incl, plugin="Rcpp")

example("dtrMatrix-class")
ff(T)

_______________________________________________
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



--
Romain Francois
Professional R Enthusiast
+33(0) 6 28 91 30 30
http://romainfrancois.blog.free.fr
|- http://bit.ly/fT2rZM : highlight 0.2-5
|- http://bit.ly/gpCSpH : Evolution of Rcpp code size
`- http://bit.ly/hovakS : RcppGSL initial release


_______________________________________________
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




--
Romain Francois
Professional R Enthusiast
+33(0) 6 28 91 30 30
http://romainfrancois.blog.free.fr
|- http://bit.ly/fT2rZM : highlight 0.2-5
|- http://bit.ly/gpCSpH : Evolution of Rcpp code size
`- http://bit.ly/hovakS : RcppGSL initial release

#include <RcppCommon.h>

// forward declaration
class dtrMatrix ; 

namespace Rcpp{
    namespace traits {
        template <>
        class is_convertible<SEXP,dtrMatrix> : public true_type{} ;
    }
}

#include <Rcpp.h>

class dtrMatrix {
protected:
    Rcpp::NumericVector d_dat;
    Rcpp::List d_dimnames;
    int d_size;                 // must be square
    bool d_upper;               // true if upper triangular
    bool d_unit;                // true if unit diagonal
public:
    dtrMatrix(Rcpp::S4&) throw (std::runtime_error);
    operator SEXP() const ;
};
      
using namespace Rcpp ;
dtrMatrix::dtrMatrix(Rcpp::S4& xp) throw (std::runtime_error)
    : d_dat(xp.slot("x")), d_dimnames(xp.slot("Dimnames")) {
    if (!xp.inherits("dtrMatrix"))
        throw std::runtime_error("constructor needs S4 class dtrMatrix");
    IntegerVector dd = xp.slot("Dim");
    if (dd.size() != 2 || dd[0] != dd[1])
        throw std::runtime_error("Matrix must be square");
    d_size = dd[0];
    std::string uplo = as<std::string>(xp.slot("uplo"));
    d_upper = (uplo == "U") || (uplo == "u");
    std::string diag = as<std::string>(xp.slot("diag"));
    d_unit = (diag == "U") || (diag == "u");
}

dtrMatrix::operator SEXP() const {
    Rcpp::S4 ans("dtrMatrix");
    ans.slot("x") = clone(d_dat);
    ans.slot("Dimnames") = clone(d_dimnames);
    IntegerVector dd(2);
    dd[0] = dd[1] = d_size;
    ans.slot("Dim") = dd;
    ans.slot("uplo") = d_upper ? "U" : "L";
    ans.slot("diag") = d_unit ? "U" : "N";
    return ans;
}

namespace Rcpp {
    
    template <>
    SEXP wrap<dtrMatrix>( const dtrMatrix& m ){
        return m ;
    }
}

library(Matrix)
library(inline)
library(Rcpp)

settings <- getPlugin( "Rcpp" )
settings$includes <- sprintf( '%s\n%s', 
    paste( readLines( "doug.cpp" ), collapse = "\n" ) , 
    settings$includes
)

code <- '
S4 s(x_) ;
dtrMatrix x(s) ;
return wrap(x);
'
ff <- cxxfunction(signature(x_ = "ANY"), code, incl, settings = settings, 
verbose = TRUE )

example("dtrMatrix-class")
ff(T)

_______________________________________________
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