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

ian.fellows at stat.ucla.edu ian.fellows at stat.ucla.edu
Sat Dec 24 08:03:00 CET 2011


I suppose that I will share my solution to this issue. I have two utility
functions:

using namespace Rcpp;

template<class T>
XPtr<T> unwrap_robject(const SEXP& sexp){
	RObject ro(sexp);
	if(ro.isObject()){
		Language call("as.environment",sexp);
		SEXP ev = call.eval();
		Language call1("get",".pointer",-1,ev);
		SEXP ev1 = call1.eval();
		XPtr<T > xp(ev1);
		return xp;
	}else{
		XPtr<T > xp(sexp);
		return xp;
	}
}

template<class T>
SEXP wrap_in_reference_class(const T& obj,std::string class_name){
	XPtr< T > xp(new T(obj));
	Language call( "new", Symbol( class_name ),xp);
	return call.eval();
}


And then for object I define something like

class MyObject{
	public:
		MyObject(SEXP sexp){
			XPtr<MyObject> xp = unwrap_object<MyObject>(sexp);
			/* copy members from xp here */
		}

		operator SEXP() const{
			return wrap_in_reference_class(*this,"MyObject");
		}
};

and create the module class:

RCPP_MODULE(MyModule){

	class_<MyObject>("MyObject")
		.constructor<SEXP>();

}

MyObject can now be passed up and down transparently from c++ to R. I am
interested to hear feedback as to whether this is a good strategy or not.


Ian


On Dec 23, 2011, at 3:16 PM, rcpp-devel-request at r-forge.wu-wien.ac.at wrote:

Send Rcpp-devel mailing list submissions to
	rcpp-devel at lists.r-forge.r-project.org

To subscribe or unsubscribe via the World Wide Web, visit
	https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel

or, via email, send a message with subject or body 'help' to
	rcpp-devel-request at lists.r-forge.r-project.org

You can reach the person managing the list at
	rcpp-devel-owner at lists.r-forge.r-project.org

When replying, please edit your Subject line so it is more specific
than "Re: Contents of Rcpp-devel digest..."


Today's Topics:

  1. g++-llvm still doesn't like RcppArmadillo? (Davor Cubranic)
  2. Re: c++ class as argument in rcpp function (using	modules)
     (Yasir Suhail)


----------------------------------------------------------------------

Message: 1
Date: Fri, 23 Dec 2011 11:03:30 -0800 (PST)
From: Davor Cubranic <cubranic at stat.ubc.ca>
Subject: [Rcpp-devel] g++-llvm still doesn't like RcppArmadillo?
To: rcpp-devel at r-forge.wu-wien.ac.at
Message-ID: <Pine.GSO.4.64.1112230955150.8116 at be.stat.ubc.ca>
Content-Type: TEXT/PLAIN; charset=US-ASCII; format=flowed

Did we ever find a way to make RcppArmadillo compile with g++-llvm
on OS X Lion?

There was a thread in July about unresolved 'arma_version' symbol
(http://lists.r-forge.r-project.org/pipermail/rcpp-devel/2011-July/002621.html),
and it appears the only way around it was by compiling with the
vanilla g++.

I just ran into the same error, using R installed from MacPorts as
the R-framework port. This uses the llvm-g++-4.2 toolchain, so
getting it to use apple-g++ to compile just RcppArmadillo would
probably require manual fiddling with the configure step, which I
would prefer to avoid given that this is on a compute cluster where
we're automating software installation and upgrading.

Also, does anyone know if this will mean that every package that
depends on RcppArmadillo will have to avoid using LLVM as well?

Installation output below:

* installing *source* package 'RcppArmadillo' ...
** package 'RcppArmadillo' successfully unpacked and MD5 sums
checked
** libs
*** arch - x86_64
/opt/local/bin/llvm-g++-4.2
-I/opt/local/Library/Frameworks/R.framework/Resources/include
-I/opt/local/Library/Frameworks/R.framework/Resources/include/x86_64
-I/opt/local/include
-I"/opt/local/Library/Frameworks/R.framework/Versions/2.14/Resources/library/Rcpp/include"
-I../inst/include -fPIC  -pipe -O2 -m64 -c RcppArmadillo.cpp -o
RcppArmadillo.o
/opt/local/bin/llvm-g++-4.2
-I/opt/local/Library/Frameworks/R.framework/Resources/include
-I/opt/local/Library/Frameworks/R.framework/Resources/include/x86_64
-I/opt/local/include
-I"/opt/local/Library/Frameworks/R.framework/Versions/2.14/Resources/library/Rcpp/include"
-I../inst/include -fPIC  -pipe -O2 -m64 -c fastLm.cpp -o fastLm.o
/opt/local/bin/llvm-g++-4.2 -dynamiclib
-Wl,-headerpad_max_install_names -undefined dynamic_lookup
-single_module -multiply_defined suppress -L/opt/local/lib
-L/opt/local/lib/llvm-gcc42 -lgfortran -o RcppArmadillo.so
RcppArmadillo.o fastLm.o
/opt/local/Library/Frameworks/R.framework/Versions/2.14/Resources/library/Rcpp/lib/x86_64/libRcpp.a
-L/opt/local/Library/Frameworks/R.framework/Resources/lib/x86_64
-lRlapack
-L/opt/local/Library/Frameworks/R.framework/Resources/lib/x86_64
-lRblas -F/opt/local/Library/Frameworks/R.framework/.. -framework R
-Wl,-framework -Wl,CoreFoundation
installing to
/opt/local/Library/Frameworks/R.framework/Versions/2.14/Resources/library/RcppArmadillo/libs/x86_64
** R
** inst
** preparing package for lazy loading
** help
*** installing help indices
** building package indices ...
*** tangling vignette sources ...
   'RcppArmadillo-unitTests.Rnw'
** testing if installed package can be loaded
Error in dyn.load(file, DLLpath = DLLpath, ...) :
  unable to load shared object
'/opt/local/Library/Frameworks/R.framework/Versions/2.14/Resources/library/RcppArmadillo/libs/x86_64/RcppArmadillo.so':

dlopen(/opt/local/Library/Frameworks/R.framework/Versions/2.14/Resources/library/RcppArmadillo/libs/x86_64/RcppArmadillo.so,
6): Symbol not found: __ZN4arma12arma_version5majorE
  Referenced from:
/opt/local/Library/Frameworks/R.framework/Versions/2.14/Resources/library/RcppArmadillo/libs/x86_64/RcppArmadillo.so
  Expected in: flat namespace
 in
/opt/local/Library/Frameworks/R.framework/Versions/2.14/Resources/library/RcppArmadillo/libs/x86_64/RcppArmadillo.so
Error: loading failed
Execution halted
ERROR: loading failed
* removing
'/opt/local/Library/Frameworks/R.framework/Versions/2.14/Resources/library/RcppArmadillo'

The downloaded packages are in
        '/private/tmp/RtmpXwDIXY/downloaded_packages'
Warning message:
In install.packages("RcppArmadillo") :
  installation of package 'RcppArmadillo' had non-zero exit status



------------------------------

Message: 2
Date: Fri, 23 Dec 2011 18:16:36 -0500
From: Yasir Suhail <yusuhail at gmail.com>
Subject: Re: [Rcpp-devel] c++ class as argument in rcpp function
	(using	modules)
To: rcpp-devel at lists.r-forge.r-project.org
Message-ID:
	<CACvQymaJpdEvkRhV5fcSoLb4OrfafMqvU+xAPj0otYQKYgtUwg at mail.gmail.com>
Content-Type: text/plain; charset="iso-8859-1"

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

------------------------------

_______________________________________________
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

End of Rcpp-devel Digest, Vol 26, Issue 22
******************************************




More information about the Rcpp-devel mailing list