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

Douglas Bates bates at stat.wisc.edu
Wed Dec 21 23:29:07 CET 2011


On Wed, Dec 21, 2011 at 3:55 PM, Yasir Suhail <yusuhail at gmail.com> wrote:
> Hi
>
> I looked up the previous thread "Creating pointers to objects and wrapping
> them"
> from http://lists.r-forge.r-project.org/pipermail/rcpp-devel/2011-April/002170.html,
> and it seems that providing a specialization of the wrap<>() function can
> help us return classes. Perhaps similarly, one could provide a
> specialization of the as<>() function for arguments? While wrap is
> implemented with the Language("new" ... function, is there any example of an
> as<>() specialization for custom classes? The vignette
> (http://dirk.eddelbuettel.com/code/rcpp/Rcpp-extending.pdf) shows a
> declaration for as, but no definitions.

It is not clear if you want to wrap the pointer to the object as an
"external pointer" in R or if you want to create an R object from your
C++ object.  Wrapping an external pointer is straightforward.  This
example from http://r-forge.r-project.org/scm/viewvc.php/pkg/lme4Eigen/src/external.cpp?view=markup&root=lme4

    // generalized linear model (and generalized linear mixed model) response

    SEXP glm_Create(SEXP fam, SEXP y, SEXP weights, SEXP offset, SEXP mu,
		    SEXP sqrtXwt, SEXP sqrtrwt, SEXP wtres, SEXP eta, SEXP n) {
	BEGIN_RCPP;
	glmResp *ans = new glmResp(List(fam), y, weights, offset, mu,
				   sqrtXwt, sqrtrwt, wtres, eta, n);
	return wrap(XPtr<glmResp>(ans, true));
	END_RCPP;
    }

    SEXP glm_setN(SEXP ptr_, SEXP n) {
	BEGIN_RCPP;
	XPtr<glmResp>(ptr_)->setN(as<MVec>(n));
	END_RCPP;
    }

shows wrapping an external pointer to return it and then passing the
external pointer to be modify the C++ object.  You should be aware,
however, that an external pointer cannot be save'd then loaded into
another R session (which makes sense if you think about it).  You need
to do a bit of dancing if you want to do that.  Essentially you must
save as R objects enough information to regenerate the C++ object then
detect if the external pointer points to NULL and regenerate the
object if it does.

>
> Thanks!
>
> Yasir
>
>
>
> On Wed, Dec 21, 2011 at 5:45 AM, <romain at r-enthusiasts.com> wrote:
>>
>> Iirc, this is not implemented yet.
>>
>> There is a chance we might add this feature in the future.
>>
>> Cheers,
>>
>> Romain
>>
>>
>>
>> Le 21 déc. 2011 à 10:59, Yasir Suhail <yusuhail at gmail.com> a écrit :
>>
>> I need to pass a class as an argument in a function I am exposing to R.
>> From the skeleton package module, let us say that I have
>>
>> class World {
>> public:
>>     World() : msg("hello"){}
>>     void set(std::string msg) { this->msg = msg; }
>>     std::string greet() { return msg; }
>>     void addMsg(World& w2) {
>> msg = msg + w2.msg;
>>     }
>> private:
>>     std::string msg;
>> };
>>
>> However, this gives errors of the sort
>>
>> /usr/local/lib/R/site-library/Rcpp/include/Rcpp/module/Module_generated_CppMethod.h:186:4:
>> error: invalid initialization of non-const reference of type ‘World&’ from
>> an rvalue of type ‘World’
>> In file included from
>> /usr/local/lib/R/site-library/Rcpp/include/RcppCommon.h:306:0,
>>                  from
>> /usr/local/lib/R/site-library/Rcpp/include/Rcpp.h:27,
>>                  from rcpp_module.cpp:1:
>> /usr/local/lib/R/site-library/Rcpp/include/Rcpp/traits/Exporter.h: In
>> constructor ‘Rcpp::traits::Exporter<T>::Exporter(SEXPREC*) [with T = World,
>> SEXPREC* = SEXPREC*]’:
>> /usr/local/lib/R/site-library/Rcpp/include/Rcpp/as.h:51:51:   instantiated
>> from ‘T Rcpp::internal::as(SEXPREC*, Rcpp::traits::r_type_generic_tag) [with
>> T = World, SEXPREC* = SEXPREC*]’
>> /usr/local/lib/R/site-library/Rcpp/include/Rcpp/as.h:75:89:   instantiated
>> from ‘T Rcpp::as(SEXPREC*) [with T = World, SEXPREC* = SEXPREC*]’
>>
>> /usr/local/lib/R/site-library/Rcpp/include/Rcpp/module/Module_generated_CppMethod.h:186:4:
>>   instantiated from ‘SEXPREC* Rcpp::CppMethod1<Class, void,
>> U0>::operator()(Class*, SEXPREC**) [with Class = World, U0 = World&,
>> SEXPREC* = SEXPREC*]’
>> rcpp_module.cpp:86:1:   instantiated from here
>> /usr/local/lib/R/site-library/Rcpp/include/Rcpp/traits/Exporter.h:31:37:
>> error: no matching function for call to ‘World::World(SEXPREC*&)’
>> rcpp_module.cpp:30:5: note: candidates are: World::World()
>> rcpp_module.cpp:28:13: note:                 World::World(const World&)
>> make: *** [rcpp_module.o] Error 1
>>
>> Looking at http://dirk.eddelbuettel.com/code/rcpp/Rcpp-extending.pdf, it
>> seems that I can extend Rcpp::as to account for my classes, but I still have
>> two questions:
>> 1. How do I define the constructor World(SEXP)? Is there a working example
>> somewhere for a user defined C++ class?
>> 2. Can I also use pointers and pass-by-reference as these are more often
>> used in real C++ code.
>>
>> In short, I'd appreciate a way to pass my C++ classes (as the class and
>> also by ref. or pointer) that have been exposed to R as arguments to exposed
>> functions. How do I achieve that?
>>
>> Thanks!
>>
>> _______________________________________________
>> 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
>
>
>
> _______________________________________________
> 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


More information about the Rcpp-devel mailing list