[Rcpp-devel] inline plug-in linking
Ian Fellows
ian.fellows at stat.ucla.edu
Sat Nov 17 21:26:53 CET 2012
Thanks for the help. I just thought I should report back with the solution to my issues for posterity.
It seems that the header only interface is the way to go for my purposes because I only have a few data structures which need to be shared across compilation units, and almost all of the code is in the headers. To expose the data structures, I created a few accessor functions like:
void registerDirectedStatistic(Rcpp::XPtr< ernm::Stat<ernm::Directed> > ps){
ernm::StatController<ernm::Directed>::addStat(
std::tr1::shared_ptr< ernm::Stat<ernm::Directed> >(ps->cloneUnsafe()));
}
Something that had tripped me up is that I had previously had my objects returning safe pointers (shared_ptr) when they were cloned. For reasons beyond my current understanding, these pointers became unsafe when passed from code compiled in inline, to the package object. This caused the segfault that I reported before. Next, I followed JJ's advise and registered the function with R, and created a macro to simplify calling
R_RegisterCCallable("ernm",
"registerDirectedStatistic",(DL_FUNC) ®isterDirectedStatistic);
#define REGISTER_DIRECTED_STATISTIC(x) ((void(*)(Rcpp::XPtr< ernm::Stat<ernm::Directed> >))R_GetCCallable("ernm", "registerDirectedStatistic"))(x)
I also exposed the function in my module.
function("registerDirectedStatistic",®isterDirectedStatistic);
So now there are two ways for the user to add Stats to the data structure. They can pass a pointer up to R, and then down to ernm.
getPointer <- cxxfunction(signature(),
"
return Rcpp::XPtr< Stat<Directed> >(new Edges2<Directed>());
",
plugin="ernm",includes=src)
pointerToNewStat <- getPointer()
registerDirectedStatistic(pointerToNewStat)
or, just register it directly in compiled code
registerEdges2Statistic <- cxxfunction(signature(),
"
Rcpp::XPtr< Stat<Directed> > ps(new Edges2<Directed>());
REGISTER_DIRECTED_STATISTIC(ps);
",
plugin="ernm",includes=src)
registerEdges2Statistic()
Best,
Ian
On Nov 16, 2012, at 8:50 AM, JJ Allaire <jj.allaire at gmail.com> wrote:
> Anyhow, I think I am probably missing some linking info from my inlinePlugIn statement.
>
> This is the key -- plugins that do linking are much more complicated than ones that rely on headers only. You can look at the Rcpp and RcppGSL packages as examples -- in short there needs to be a function inside the package that can cough up the correct library locations. If you get this far then your stuff will work with inline and Rcpp::cppFunction, however people developing packages that want to link against your stuff will need custom Makevars entries (which you can configure the inline plugin to produce, but by now things have gotten pretty complicated for your users).
>
> If you can manage to do header-only "linking" that will be much, much simpler. At the lowest level the key to this is R_GetCCallable. In Rcpp land there is a GetCppCallable equivalent that works with modules. You can see the use of this in the header file which is generated by Rcpp::interfaces(r, cpp).
>
> If you want to expose the data structure using this mechanism then you could write a function like this:
>
> // [[Rcpp::export]]
> Rcpp::List getModelStatistics() {
> return StatController::getModelStatistics();
> }
>
> And then compileAttributes will automatically generate the shim that calls GetCppCallable.
>
>
More information about the Rcpp-devel
mailing list