Skip to content

[Rcpp-devel] named and default arguments in exposed C++ classes

4 messages · Andreas Prescher, Dirk Eddelbuettel

#
Hello,

I wrote a R package using Rcpp (0.10.4) modules
to expose my C++ classes.

All works fine, but for convenient using from R,
it would be great to use the class methods with
named arguments and default arguments.

At the moment I have to use all class methods as
declared in the corresponding C++ header files.

something like this:
RCPP_MODULE(PsiMin) {

class_<Foo>( "Foo" )
..method( "bar", &Foo::bar); }

class Foo  {

int bar(int x, int y = 2) {return x + y};
}

using from R
 > f <- new(Foo)
 > f$bar(x = 1) => 3
 > f$bar(x = 1, y = 1) => 2

I only can call my methods like this:
 > f$bar(3,4) => 7

Is there a workaround to make named/default
arguments working when using classes?

E.g. make some "mix" with 'function'
and 'class_'.

Any suggestions would be great.

Andreas
#
On 5 March 2014 at 16:26, Andreas Prescher wrote:
| Hello,
| 
| I wrote a R package using Rcpp (0.10.4) modules
| to expose my C++ classes.
| 
| All works fine, but for convenient using from R,
| it would be great to use the class methods with
| named arguments and default arguments.
| 
| At the moment I have to use all class methods as
| declared in the corresponding C++ header files.
| 
| something like this:
| RCPP_MODULE(PsiMin) {
| 
| class_<Foo>( "Foo" )
| ..method( "bar", &Foo::bar); }
| 
| class Foo  {
| 
| int bar(int x, int y = 2) {return x + y};
| }
| 
| using from R
|  > f <- new(Foo)
|  > f$bar(x = 1) => 3
|  > f$bar(x = 1, y = 1) => 2
| 
| I only can call my methods like this:
|  > f$bar(3,4) => 7
| 
| Is there a workaround to make named/default
| arguments working when using classes?
| 
| E.g. make some "mix" with 'function'
| and 'class_'.
| 
| Any suggestions would be great.

In RcppCNPy I use free functions exposed via Rcpp Modules and that works:

  R> library(RcppCNPy)
  R> npyLoad
  internal C++ function <0x19721a0>
      docstring : read an npy file into a numeric or integer vector or matrix
      signature : Rcpp::RObject npyLoad(std::string, std::string, bool)
  R> args(npyLoad)
  function (filename, type = "numeric", dotranspose = TRUE) 
  NULL
  R> str(npyLoad(file="/home/edd/git/rcppcnpy/tests/fvec.npy"))
   num [1:5] 0 1.1 2.2 3.3 4.4
  R> 

If it doesn't work that way for autoexported member functions you may need to
a) live with it, b) but a wrapper function around it or c) patch Rcpp Modules.

Dirk
#
Thanks a lot for your quick response,

I got a working version, also inspired by
your comments from
http://stackoverflow.com/questions/12405655/returning-a-custom-object-from-a-wrapped-method-in-rcpp.

I did something like this in my simple example
(maybe some typos, I tried with my real package..)

for Foo:

template <> Foo* as( SEXP obj)
{
	Rcpp::Environment e(obj);
   	Rcpp::XPtr<Foo> exPointer( (SEXP) e.get(".pointer") );
   	return (Foo*) exPointer;
}

RCPP_EXPOSED_CLASS(Foo)

SEXP createFoo() {
     Rcpp::XPtr<Foo> exPointer( new Foo(), true ) ;
     Function maker=Environment::Rcpp_namespace()[ "cpp_object_maker"];
     return maker ( typeid(Foo).name() , exPointer );
}
int bar(Foo* f,int x, int y) {return f->bar(x,y);}

RCPP_MODULE(PsiMin) {
	function( "createFoo", &createFoo);
	function( "bar", &bar, List::create(_["f"], _["x"], _["y"] = 2));	
}
in R:
 > f <- createFoo()
 > bar(f = f, x = 3);

Is this OK, are there some memory issues I've overlooked?

What I'm now thinking of (because in my case there are
normally only 1-16 objects created, depending on the cpu cores),
is to store the objects on the C++ side,
so a call of
bar(f = f, x = 3);
would be
bar(3) //calling first object Foo::f inside package

But what is with the  allocated memory?
Of course I could write a cleanup method,
but this seems not very elegant.

Is there a safe way, some kind of "hooked method",
that will be always called when the module
is unloaded. I only found the finalize method
in the modules/class context.

(Maybe a question for a new thread)


Andreas





Am 05.03.2014 16:36, schrieb Dirk Eddelbuettel:
#
On 6 March 2014 at 15:52, Andreas Prescher wrote:
| Thanks a lot for your quick response,
| 
| I got a working version, also inspired by
| your comments from
| http://stackoverflow.com/questions/12405655/returning-a-custom-object-from-a-wrapped-method-in-rcpp.
| 
| I did something like this in my simple example
| (maybe some typos, I tried with my real package..)
| 
| for Foo:
| 
| template <> Foo* as( SEXP obj)
| {
| 	Rcpp::Environment e(obj);
|    	Rcpp::XPtr<Foo> exPointer( (SEXP) e.get(".pointer") );
|    	return (Foo*) exPointer;
| }
| 
| RCPP_EXPOSED_CLASS(Foo)
| 
| SEXP createFoo() {
|      Rcpp::XPtr<Foo> exPointer( new Foo(), true ) ;
|      Function maker=Environment::Rcpp_namespace()[ "cpp_object_maker"];
|      return maker ( typeid(Foo).name() , exPointer );
| }
| int bar(Foo* f,int x, int y) {return f->bar(x,y);}
| 
| RCPP_MODULE(PsiMin) {
| 	function( "createFoo", &createFoo);
| 	function( "bar", &bar, List::create(_["f"], _["x"], _["y"] = 2));	
| }
| in R:
|  > f <- createFoo()
|  > bar(f = f, x = 3);
| 
| Is this OK, are there some memory issues I've overlooked?
| 
| What I'm now thinking of (because in my case there are
| normally only 1-16 objects created, depending on the cpu cores),
| is to store the objects on the C++ side,
| so a call of
| bar(f = f, x = 3);
| would be
| bar(3) //calling first object Foo::f inside package
| 
| But what is with the  allocated memory?

If it is within C++ scope, you get C++ scope behaviour, ie default destructors
will be invoked.

| Of course I could write a cleanup method,
| but this seems not very elegant.

Hard to say based on the toy example.  You could always proceed and the
(memory) profile later...
 
| Is there a safe way, some kind of "hooked method",
| that will be always called when the module
| is unloaded. I only found the finalize method
| in the modules/class context.

That's the one.

Dirk

| 
| (Maybe a question for a new thread)
| 
| 
| Andreas
| 
| 
| 
| 
| 
| Am 05.03.2014 16:36, schrieb Dirk Eddelbuettel:
| >
| > On 5 March 2014 at 16:26, Andreas Prescher wrote:
| > | Hello,
| > |
| > | I wrote a R package using Rcpp (0.10.4) modules
| > | to expose my C++ classes.
| > |
| > | All works fine, but for convenient using from R,
| > | it would be great to use the class methods with
| > | named arguments and default arguments.
| > |
| > | At the moment I have to use all class methods as
| > | declared in the corresponding C++ header files.
| > |
| > | something like this:
| > | RCPP_MODULE(PsiMin) {
| > |
| > | class_<Foo>( "Foo" )
| > | ..method( "bar", &Foo::bar); }
| > |
| > | class Foo  {
| > |
| > | int bar(int x, int y = 2) {return x + y};
| > | }
| > |
| > | using from R
| > |  > f <- new(Foo)
| > |  > f$bar(x = 1) => 3
| > |  > f$bar(x = 1, y = 1) => 2
| > |
| > | I only can call my methods like this:
| > |  > f$bar(3,4) => 7
| > |
| > | Is there a workaround to make named/default
| > | arguments working when using classes?
| > |
| > | E.g. make some "mix" with 'function'
| > | and 'class_'.
| > |
| > | Any suggestions would be great.
| >
| > In RcppCNPy I use free functions exposed via Rcpp Modules and that works:
| >
| >    R> library(RcppCNPy)
| >    R> npyLoad
| >    internal C++ function <0x19721a0>
| >        docstring : read an npy file into a numeric or integer vector or matrix
| >        signature : Rcpp::RObject npyLoad(std::string, std::string, bool)
| >    R> args(npyLoad)
| >    function (filename, type = "numeric", dotranspose = TRUE)
| >    NULL
| >    R> str(npyLoad(file="/home/edd/git/rcppcnpy/tests/fvec.npy"))
| >     num [1:5] 0 1.1 2.2 3.3 4.4
| >    R>
| >
| > If it doesn't work that way for autoexported member functions you may need to
| > a) live with it, b) but a wrapper function around it or c) patch Rcpp Modules.
| >
| > Dirk
| >
| 
| 
| _______________________________________________
| Rcpp-devel mailing list
| Rcpp-devel at lists.r-forge.r-project.org
| https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel