0

I am using Rcpp to create a package in R that leverages C++ code. I have read all of the Rcpp vignettes, but I haven't been able to find a solution to the following problem.

One of the C++ classes I'm trying to use contains a pointer. I am exposing the class using a module. When I try to install the package in R, I get the following error.

error: expected unqualified-id before '*' token.field("*w", &ffm_model::*w)

What am I doing wrong?

Code for Class Containing Pointer

typedef float ffm_float;
typedef int ffm_int;

class ffm_model {
  public:
    ffm_int n; // number of features
    ffm_int m; // number of fields
    ffm_int k; // number of latent factors
    ffm_float *w = nullptr;
    bool normalization;
    ~ffm_model();
};

Code for Corresponding RCPP Module

RCPP_MODULE(ffmModelMod){
  using namespace Rcpp;

  //Expose class as ffm_model on the r side
  class_<ffm_model>( "ffm_model")

    .field("n", &ffm_model::n)
    .field("m", &ffm_model::m)
    .field("k", &ffm_model::k)
    .field("*w", &ffm_model::*w)
    .field("normalization", &ffm_model::normalization)
    .method("~ffm_model",&ffm_model::~ffm_model)
    ;
}
dstrants
  • 7,423
  • 2
  • 19
  • 27
ndroz
  • 31
  • 2
  • `float*` or `double*` is NOT a type that can be mapped automatically to a `SEXP`, which is what the compiler tells you with the error. You also cannot declare the dtor method. Looks into `Rcpp::XPtr` to wrap a pointer, – Dirk Eddelbuettel Mar 27 '18 at 18:39
  • Thanks, Dirk. I will look into Rcpp::XPtr. As for the dtor method... Is this something that can be solved with Rcpp::XPtr as well? – ndroz Mar 27 '18 at 19:29
  • You can also stay with modules, but you still need `XPtr` on the interface. And you should not need an explicit dtor. – Dirk Eddelbuettel Mar 27 '18 at 19:30
  • I think I will stick with modules and then use XPtr on the interface. What documentation do you recommend I read to get me started? I have already gone through the Rcpp "extending" and "modules" vignettes, but I still don't fully understand how to integrate XPtr with modules. – ndroz Mar 27 '18 at 20:16

1 Answers1

1

I had a similar problem, and as Dirk mentions, it is due to types that cannot be mapped automatically, such as float*.

The following workaround works for me:

  1. Do not expose the fields with problematic types to R.
  2. Instead, expose get() and set() functions to the fields above.

Here is an example, in which both the (unproblematic) value field and the (problematic) child field (a pointer to an object of the same class) are hidden:

Class

#include <Rcpp.h>
using namespace Rcpp;

class node
{
public:
    double value; // Voluntarily hidden from R
    node* child; // Must be hidden from R

    // Exposed functions
    void setVal(double value);
    double getVal();

    node* createNode(double value); // return pointer to a node
    node* createChild(double value); // set child
    node* getChild();

};

Methods

void node::setVal(double value){
    this->value = value;
}
double node::getVal(){
    return this->value;
} 
node* node::createNode(double value){
    node* n = new node;
    n->value = value;
    return n;
}
node* node::createChild(double value){
    this->child = createNode(value);
    return child;
}
node* node::getChild(){
    return this->child;
}

RCPP Module

RCPP_MODULE(gbtree_module){
    using namespace Rcpp;
    class_<node>("node")
        .constructor()
      .method("setVal", &node::setVal)
      .method("getVal", &node::getVal)
      .method("createNode", &node::createNode)
      .method("createChild", &node::createChild)
      .method("getChild", &node::getChild)
    ;
}

Usage in R

n <- new(node)
n$setVal(2)
n$getVal()
n2 <- n$createNode(1) # unrelated node
n3 <- n$createChild(3) #child node
n$getChild() #pointer to child node
n3