[Rd] Dynamic linking to binary code from other packages??
dankoc at gmail.com
Thu Nov 13 20:42:53 CET 2008
Thanks very much for all of the detailed responses! I am beginning to
understand how all of this can work, and learning quite a bit about
the C language in the process!
Can this be applied to either C++ classes or to member functions of a
class? Please forgive my lack of general C/C++ knowledge, which may
be abundantly clear in my specific questions:
It seems pretty clear that one may not register a pointer to a class
declaration and share it in this way?!
Will it work to register a pointer to a class' member functions, using
the code described by either Jeff or Simon? I looked into this, and
am pretty sure that it can not work. (Here is a good article on
registering a pointer to a class' member function:
So, is there any way to share either C++ classes or class member
functions with another package in R?
Again, please do forgive my inexperience.
On Thu, Nov 13, 2008 at 9:15 AM, Simon Urbanek
<simon.urbanek at r-project.org> wrote:
> On Nov 12, 2008, at 23:16 , Jeff Ryan wrote:
>>> I've looked through the "Writing R Extensions" manual, and can't find
>>> this documented very clearly. A previous question to the list gave me
>>> the very kind response pasted below. I've looked at the suggested
>>> examples (lme4 using C functions from Matrix).
>> It isn't really "clearly" explained. I will give it a try though.
>> You can't use compiled/packaged functions from within _your_ compiled
>> code unless the package that you are referring to (affxparser) makes
>> them available for export.
>> If affxparser doesn't do this you are back to Dirk's method.
>> For the sake of others who have gone down this road I will explain
>> what I know, and probably in the process learn what I may be doing
>> wrong. (all of this I learned by reading the sources for R and lme4
>> and Matrix).
>> Matrix has a copy of the Matrix.h header in its /inst directory,
>> specifically /inst/include/Matrix.h
>> This gets installed as /include/Matrix.h, which is where LinkingTo
>> links to during compilation.
>> You (or the affxparser author) will also need a handful of C calls
>> that are complementary to ones in the package you are getting the
>> functions from.
>> An example from Matrix:
>> /include/Matrix_stubs.c contains
>> CHM_DN attribute_hidden
>> M_as_cholmod_dense(CHM_DN ans, SEXP x)
>> static CHM_DN(*fun)(CHM_DN,SEXP) = NULL;
>> if(fun == NULL)
>> fun = (CHM_DN(*)(CHM_DN,SEXP))
>> R_GetCCallable("Matrix", "as_cholmod_dense");
>> return fun(ans, x);
> FWIW this is not exactly the most efficient way to do it. It's much easier
> to do it the commonly used way of setting the function pointers directly
> (taking the situation above):
> in the initialization function of the package populate all the pointers:
> M_as_cholmod_dense = (CHM_DN(*)(CHM_DN,SEXP)) R_GetCCallable("Matrix",
> By setting the functions right away you save yourself the trouble of
> checking it on every call and using a function call twice. This allows you
> to use the function transparently in your code, so you don' t need any
> function wrappers:
> x = M_as_cholmod_dense(a, b);
> This is pretty much standard C programming, so the above should be quite
> obvious (I hope).
> The only reason to do it the complicated way above is if you want to do some
> extra processing in the wrapper function so your function pointer is not
> visible from outside the function.
>> The above is far from obvious, so I will try my best to explain.
>> With respect to the R_GetCCallable call, Writing R Extensions says:
>> " p_myCfun = R_GetCCallable("packA", "myCfun");
>> The author of packB is responsible for ensuring that p_myCfun has an
>> appropriate declaration. What exactly that means was hard to determine
>> at first."
>> Taking the first line, the first CHM_DN is the function return type
>> (could be int, SEXP, etc), and the second (along with the SEXP) is the
>> argument type(s).
>> Generalized you'd have something like:
>> SEXP attribute_hidden
>> FUNNAME(SEXP ans, SEXP x)
>> static SEXP(*fun)(SEXP,SEXP) = NULL;
>> if(fun == NULL)
>> fun = (SEXP(*)(SEXP,SEXP))
>> R_GetCCallable("PACKAGE", "FUNCTION");
>> return fun(ans, x);
>> lme4 then simply "#include"s this .c file in a file
>> /src/local_stubs.c, which is compiled right along side of the src code
>> in lme4.
>> At this point you can then use the functions that are
>> 'exported/registered' as you would a C function defined in your own
>> The other side of this is what the Matrix (affxparser?) package needs
>> to do. It needs a registration routine that specifically registers
>> the routines as callable using:
>> R_RegisterCCallable (which is documented in Writing R Extensions)
>> In Matrix this is in /src/init.c via a macro.
>> A simpler in-progress bit of code can be found in the /dev branch of
>> xts on R-forge. Take a look at
>> As far as C++ goes, I would suspect the Matrix package again has all
>> the bits you are looking for.
>> Jeffrey Ryan
>> jeffrey.ryan at insightalgo.com
>> ia: insight algorithmics
>> R-devel at r-project.org mailing list
More information about the R-devel