[Rcpp-devel] "binding" Rcpp::InternalFunction or Rcpp::CppFunction
Christian Authmann
authmanc at Mathematik.Uni-Marburg.de
Fri Aug 1 13:17:13 CEST 2014
Hello,
I'd like to do something similar to
Foo getdata(DataProvider *p, int id) {
return p->getData(id);
}
DataProvider provider(/* arguments specifying data source*/);
RInside R;
R["getdata"] = Rcpp::InternalFunction( std::bind(getdata, &provider) );
The idea is that I can export a getter for each available provider and
the R script will pick the correct one just by calling the correct function.
id <- 42
d <- getdata(id)
Of course the code above won't work, since CppFunction uses plain
function pointers instead of std::function - there's no way to turn a
bind'ed std::function back into a function pointer. And we cannot use
c++11's std::function in rcpp since CRAN won't allow it (or did that
change?)
So instead I tried the old "userdata"-idiom, where you pass a void* to
the wrapper, which gets passed back as a parameter when calling. I added
a bunch of CppFunction implementations. They take the userdata-pointer
in their constructor and store it, and on operator() the
userdata-pointer is passed as the first argument. For example:
------- snip -------
template <typename RESULT_TYPE, typename U0>
class CppFunctionWithUserdata1 : public CppFunction {
public:
CppFunctionWithUserdata1(RESULT_TYPE (*fun)(void*,U0) , void
*userdata, const char* docstring = 0) : CppFunction(docstring),
ptr_fun(fun), ptr_userdata(userdata) {}
SEXP operator()(SEXP* args) {
BEGIN_RCPP
typename traits::input_parameter< U0 >::type x0(args[0]);
return Rcpp::module_wrap<RESULT_TYPE>(ptr_fun(ptr_userdata, x0));
END_RCPP
}
inline int nargs() { return 1; }
inline void signature(std::string& s, const char* name) {
Rcpp::signature<RESULT_TYPE,U0>(s, name); }
inline DL_FUNC get_function_ptr() { return (DL_FUNC)ptr_fun ; }
private:
RESULT_TYPE (*ptr_fun)(void*,U0) ;
void *ptr_userdata;
};
------- snip -------
With another constructor to InternalFunction, I can now do:
R["getdata"] = Rcpp::InternalFunction( getdata, (void *) &provider );
which compiles and works just fine. (as long as getdata() adds a cast
back from void* to DataProvider*)
But I don't know if this is safe to do, because CppFunction can return a
plain function pointer in get_function_ptr(), and that will point to a
function which neither matches the signature() nor the nargs().
get_function_ptr() is a public method, and will also be exported via the
public interface in modules/Module.h
So if someone grabs that function pointer and tries calling it
themselves instead of using CppFunction::operator(), things will blow
up. Is it likely that someone, somewhere does something like that?
So what's the way forward?
a) screw it, nobody but me needs this feature and it won't be committed
anyway
b) it's safe, I'll get it fleshed out and try submitting a pull request
to rcpp-scripts and rcpp
c) it's unsafe and unfeasible to do
d) it's unsafe. Instead I'll try to create a new class similar to
CppFunction, but without exporting a function pointer or depending on
Module.h - or maybe integrating the functionality into InternalFunction
itself, so it won't need to delegate to another class. I don't yet know
enough to say if this is feasible.
e) some other approach you'll advise me of ;)
Thanks again for your help,
Christian
--
Christian Authmann
Philipps-Universität Marburg
Fachbereich Mathematik und Informatik
AG Datenbanksysteme
Hans-Meerwein-Straße
D-35032 Marburg
More information about the Rcpp-devel
mailing list