[Rcpp-devel] RInside: C/C++ function(s) passed to R?

Serguei Sokol serguei.sokol at gmail.com
Wed Nov 13 15:48:45 CET 2019


Le 13/11/2019 à 09:31, LEVRA-JUILLET William a écrit :
> Thx Sergei,
> 
> Yes you're right, I want to use my c++ function as a R function.
> Sorry about the Banana function that takes 2 scalars, you’re right again, it should take a vector as input.
> Please ignore this for now (this is a dummy example)
> 
> My c++ "Banana" function is already compiled in my project by the time I start he R session (via RInside).
> I can pass it to R via a XPtr.
> Something like R["myfuncptr"] = Rcpp::XPtr<func_type>(new func_type (Banana));
> So, in R I got "myfuncptr" which is an "externalptr".
> 
> Now my only problem is to make that "externalptr" seen as a R function in R.
> Maybe with something like a ".Call(externalptr, param...)"?
> Here (https://stackoverflow.com/questions/13904786/r-pointer-to-c-function), Romains says something about wrapping the external pointer into an R function...
> But I struggle to find the correct way to achieve this with the function parameters...
Well, I won't help you in this fight against XPtrs but I have made my 
own hack without them and it works on my Linux. May be it will inspire 
you to smth useful.

8<------file optim2.cpp
#include <RInside.h>
using namespace Rcpp;

double Banana(double x, double y) {return (1-x)*(1-x)+100*(y-x*x)*(y-x*x);};
RcppExport SEXP wrap_banana(SEXP xSEXP, SEXP ySEXP) {
BEGIN_RCPP
     Rcpp::RObject rcpp_result_gen;
     Rcpp::traits::input_parameter< double >::type x(xSEXP);
     Rcpp::traits::input_parameter< double >::type y(ySEXP);
     rcpp_result_gen = Rcpp::wrap(Banana(x, y));
     return rcpp_result_gen;
END_RCPP
}

int main(int argc, char *argv[]) {
    RInside R(argc, argv);
    R.parseEval("dyn.load('optim2.so'); fn <- function(v) 
invisible(.Call('wrap_banana', v[1L], v[2L]))");
    Rcpp::RObject res = R.parseEval("optim(c(-2,-2), fn)");
    Rf_PrintValue(res);
    return 0;
}
8<------end of file optim2.cpp

In classical makefile I had to modify implicit rules to produce and use 
an intermidiate .so library (which is loaded in R session):
%.so:	%.cpp
	$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(RINSIDELIBS) -fPIC -shared $< -o $@
%:	%.so
	$(CXX) $^ $(LDLIBS) -o $@

Best,
Serguei.

> 
> Thank you
> William
> 
> 
> 
> 
> -----Message d'origine-----
> De : Serguei Sokol <serguei.sokol at gmail.com>
> Envoyé : mardi 12 novembre 2019 17:49
> À : LEVRA-JUILLET William <william.levra-juillet at addactis.com>; rcpp-devel at lists.r-forge.r-project.org
> Objet : Re: [Rcpp-devel] RInside: C/C++ function(s) passed to R?
> 
> Le 08/11/2019 à 11:06, LEVRA-JUILLET William a écrit :
>> Hi all,
>>
>> I’m evaluating RInside/Rcpp to interact our C++ project with R.
>>
>> I’ve seen the samples to get/set data (matrix, dataframes, etc)
>> to/from R and it builds/works fine.
>>
>> (Using gcc/mingw compiler from RTools on Windows)
>>
>> My questions is about functions…
>>
>> My project is C++, and it uses RInside to call R from our code.
>>
>> Let’s say I have a C++ function implemented in my project, and I want
>> to pass that c++ function to R so it can be “used” as a R function
>> (typically passed as argument to optim/optimize)
>>
>> I couldn’t find a way to do that using RInside.
>>
>> Ideally, I’d like to achieve something like:
>>
>> #include <RInside.h>
>>
>> double Banana(double x, double y)
>>
>> {
>>
>> return (1-x)*(1-x)+100*(y-x*x)*(y-x*x);
>>
>> }
>>
>> Int main()
>>
>> {
>>
>> RInside R(argc,, argv);
>>
>> R[“fn”] = Banana;
>>
>> R.parseEval(“optim(c(-2,-2), fn”);
>>
>> }
>>
>> I believe it’s similar to
>> https://stackoverflow.com/questions/53729493/rinside-wrapping-a-c-func
>> tion-for-use-in-an-r-function
>>
>> But I can’t really understand the Rcpp::XPtr suggestion from Dirk.
>>
>> Any help or pointers welcome J
> Sorry for a late comment but for what it's worth, XPtr won't help here as optim() expects an R function, not C++ pointer to a function.
> Moreover, this R function takes only one argument -- a vector, not a couple of scalars. So maybe you meant something similar to:
> #include <RInside.h>
> int main(int argc, char *argv[]) {
>      RInside R(argc, argv);
>      R.parseEval("Rcpp::cppFunction('double Banana(double x, double y) {return (1-x)*(1-x)+100*(y-x*x)*(y-x*x);};', cacheDir='lib')");
>      R.parseEval("fn <- function(p, ...) Banana(p[1L], p[2L])");
>      Rcpp::RObject res = R.parseEval("optim(c(-2,-2), fn)");
>      Rf_PrintValue(res);
>      return 0;
> }
> 
> which prints:
> 
> $par
> [1] 0.9990277 0.9977136
> 
> $value
> [1] 1.269722e-05
> 
> $counts
> function gradient
>        157       NA
> 
> $convergence
> [1] 0
> 
> $message
> NULL
> 
> As already underlined by others this is a sub-optimal way to use C++ functions in R but here it is imposed by optim() interface. For better designed interfaces (at least from "optimality of R/C++ exchanges" point of view) refer to examples cited by Dirk and Inaki.
> 
> Best,
> Serguei.
> 
>>
>> Thx a mil
>>
>> mailbox:///home/sokol/.thunderbird/r8hre4b3.default/Mail/pop.insa-tlse
>> .fr/Inbox?number=44&header=quotebody&part=1.1.2&filename=image005.jpg
>> <https://addactis.letsignit.com/r/32/6de77c22-c065-4906-899e-eec38189d
>> 60a/undefined>
>>
>> mailbox:///home/sokol/.thunderbird/r8hre4b3.default/Mail/pop.insa-tlse
>> .fr/Inbox?number=44&header=quotebody&part=1.1.3&filename=image006.png
>> <https://addactis.letsignit.com/r/199/c042c4a7-2508-4bf6-801a-4eeb0977
>> 8ade/undefined>
>> mailbox:///home/sokol/.thunderbird/r8hre4b3.default/Mail/pop.insa-tlse
>> .fr/Inbox?number=44&header=quotebody&part=1.1.4&filename=image007.png
>> <https://addactis.letsignit.com/r/42/b8791eba-0dab-4aa1-ab9d-813a5f8be
>> 48d/undefined>
>> mailbox:///home/sokol/.thunderbird/r8hre4b3.default/Mail/pop.insa-tlse
>> .fr/Inbox?number=44&header=quotebody&part=1.1.5&filename=image008.png
>> <https://addactis.letsignit.com/r/45/15ea361f-f441-4b13-94a0-4bdb30820
>> d9a/undefined>
>>
>> 		
>>
>>
>> *   William **LEVRA-JUILLET*
>>      Senior Software Architect
>> *   ADDACTIS Software*
>>      +33 (0)4 81 92 13 00
>>
>>
>> www.addactis.com
>> <https://addactis.letsignit.com/r/32/91871b88-8586-4561-b012-50a3a7925
>> 27a/undefined>
>>
>> <https://addactis.letsignit.com/r/32/cf8ac9eb-d46f-4524-bc9e-5cdb532be
>> f11/undefined>
>>
>> <https://addactis.letsignit.com/r/199/49e483e9-091d-4caf-a1b4-7e37d9c9
>> ac9e/undefined>
>> <https://addactis.letsignit.com/r/42/72f7499f-cd02-4bd4-835a-88f1053ca
>> bf2/undefined>
>> <https://addactis.letsignit.com/r/45/b9ce1c50-1455-48cb-b90f-b8348d799
>> 476/undefined>
>>
>> 		
>>
>>
>> *   William **LEVRA-JUILLET*
>>      Senior Software Architect
>> *   ADDACTIS Software*
>>      +33 (0)4 81 92 13 00
>>
>>
>> www.addactis.com
>> <https://addactis.letsignit.com/r/32/9cd210c2-e7cd-4d30-995a-e3ba4da16
>> 780/undefined>
>>
>>
>> _______________________________________________
>> 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-deve
>> l
>>
> 
> _______________________________________________
> 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