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
_______________________________________________
Rcpp-devel mailing list
[email protected]
https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel

Reply via email to