Dear list, 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: http://www.goingware.com/tips/member-pointers.html). 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. Best, Charles On Thu, Nov 13, 2008 at 9:15 AM, Simon Urbanek <[EMAIL PROTECTED]> wrote: > On Nov 12, 2008, at 23:16 , Jeff Ryan wrote: > >> Charles, >> >>> 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): > > CHM_DN(*M_as_cholmod_dense)(CHM_DN,SEXP); > > in the initialization function of the package populate all the pointers: > > M_as_cholmod_dense = (CHM_DN(*)(CHM_DN,SEXP)) R_GetCCallable("Matrix", > "as_cholmod_dense"); > > 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. > > Cheers, > Simon > > >> 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 >> package. >> >> 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 >> >> http://r-forge.r-project.org/scm/?group_id=118 >> >> /dev/src/init.c >> /dev/inst/include/xts.h >> /dev/inst/include/xts_stubs.c >> >> As far as C++ goes, I would suspect the Matrix package again has all >> the bits you are looking for. >> >> HTH >> Jeff >> >> >> >> >> -- >> Jeffrey Ryan >> [EMAIL PROTECTED] >> >> ia: insight algorithmics >> www.insightalgo.com >> >> ______________________________________________ >> R-devel@r-project.org mailing list >> https://stat.ethz.ch/mailman/listinfo/r-devel >> >> > > ______________________________________________ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel