[R] One package calling C-code from another package.

Duncan Temple Lang duncan at research.bell-labs.com
Fri Nov 9 22:48:52 CET 2001


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
_._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._



More information about the R-help mailing list