Ole Christensen
2001-Nov-09 18:40 UTC
[R] One package calling C-code from another package.
Dear R people We have two packages, where the first package (geoR) is required by the second (geoRglmm). Both packages have functions calling C-code via .C(). We would like to call C-functions included in the first package from within the C-code in the second package. Is this possible? An appropriate header file was included in the src directory of the second package but this alone did not solve the problem, probably because we have to link things properly when compiling the second package. We've browse the "Writing R extensions" manual and tried to use "Makevars" but we did not succeed/got it right. Any ideas? Thanks in advance for any help Ole Christensen / Paulo Ribeiro> version_ platform i686-pc-linux-gnu arch i686 os linux-gnu system i686, linux-gnu status major 1 minor 3.1 year 2001 month 08 day 31 language R -- Ole F. Christensen Department of Mathematics and Statistics Fylde College, Lancaster University Lancaster, LA1 4YF, England -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- r-help mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html Send "info", "help", or "[un]subscribe" (in the "body", not the subject !) To: r-help-request at stat.math.ethz.ch _._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._
Duncan Temple Lang
2001-Nov-09 21:48 UTC
[R] One package calling C-code from another package.
Hi Ole, This is an interesting question to handle generally. However, if you want a Linux-specific solution, the answer is reasonably simple. The dyn.load() function has an argument named local and on Linux and some other operating systems, you can do the following dyn.load("bar.so", local = FALSE) dyn.load("foo.so") and then the symbols that are referenced in foo.so but that are actually in bar.so will be available to foo.so and all will work. Here's a simple example In bar.c, put void myFoo(char **names) { fprintf(stderr, "In myFoo %s\n", names[0]);fflush(stderr); } In foo.c, put void myCall() { char *str = "from myCall"; fprintf(stderr, "In myCall\n");fflush(stderr); myFoo(&str); } and then compile bar.so and foo.so as R CMD SHLIB -o bar.so bar.c and R CMD SHLIB -o foo.so foo.o Then in R> dyn.load("bar.so",local=FALSE) > dyn.load("foo.so")> .C("myFoo", letters[1:2])In myFoo a [[1]] [1] "a" "b"> .C("myCall")In myCall In myFoo from myCall list() Note that the order in which you load the shared libraries is important. (Unless you exercise the now argument which makes the solution even more OS-dependent.) AND NOW THE BAD NEWS. If you expect this to work on Windows you may be expecting too much. Instead there are two solutions available to you. The first is to take the set of routines that are called by _both_ libraries and put them into a 3rd libary, say libMyUtils.so Then, link foo.so and bar.so against that library and they will both work correctly. Even with this approach, if you have global variables/data in the library, things will not always work as expected and you may end up with two separate copies of those variables. This may not be what you want and it is very OS and dynamic loader specific. A second approach is to explicitly look up the symbol you want. You can ask R to fetch the symbol in the other library and then invoke. This makes the C code more ugly but will work in most if not all circumstances. So for example, in foo.c, if I want to call myFoo(), I ask R for a reference to the myCall() routine and then invoke that pointer. void myRCall() { Sig f; char *str = "from myCall"; fprintf(stderr, "In myCall\n");fflush(stderr); f = (Sig) R_FindSymbol("myFoo","bar", NULL); if(f) f(&str); } Of course, if you were invoking the routine in many places in the code, you could do the lookup when the library is loaded and store the addresses in an array or structure and write the calls to refer to those. Hopefully you only care about the Linux-specific solution and using the local = FALSE approach will suffice. D. Ole Christensen wrote:> Dear R people > > We have two packages, where the first package (geoR) is required by the > second (geoRglmm). > Both packages have functions calling C-code via .C(). > > We would like to call C-functions included in the first package > from within the C-code in the second package. > Is this possible? > > An appropriate header file was included in the src directory of the > second package but this alone did not solve the problem, probably > because we have to link things properly when compiling the second > package. > > We've browse the "Writing R extensions" manual and tried to use > "Makevars" but we did not succeed/got it right. > > Any ideas? > > Thanks in advance for any help > Ole Christensen / Paulo Ribeiro > > > > version > _ > platform i686-pc-linux-gnu > arch i686 > os linux-gnu > system i686, linux-gnu > status > major 1 > minor 3.1 > year 2001 > month 08 > day 31 > language R > > > > -- > Ole F. Christensen > Department of Mathematics and Statistics > Fylde College, Lancaster University > Lancaster, LA1 4YF, England > -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- > r-help mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html > Send "info", "help", or "[un]subscribe" > (in the "body", not the subject !) To: r-help-request at stat.math.ethz.ch > _._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._-- _______________________________________________________________ Duncan Temple Lang duncan at research.bell-labs.com Bell Labs, Lucent Technologies office: (908)582-3217 700 Mountain Avenue, Room 2C-259 fax: (908)582-3340 Murray Hill, NJ 07974-2070 http://cm.bell-labs.com/stat/duncan -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- r-help mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html Send "info", "help", or "[un]subscribe" (in the "body", not the subject !) To: r-help-request at stat.math.ethz.ch _._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._