From romain.francois at dbmail.com  Thu Feb 11 10:58:42 2010
From: romain.francois at dbmail.com (Romain Francois)
Date: Thu, 11 Feb 2010 10:58:42 +0100
Subject: [Rd] LinkingTo and C++
In-Reply-To: <4B73C916.4090705@r-enthusiasts.com>
References: <4B73C916.4090705@r-enthusiasts.com>
Message-ID: <4B73D4D2.3030808@dbmail.com>

On 02/11/2010 10:08 AM, Romain Francois wrote:
>
> Hello,
>
> I've been trying to make LinkingTo work when the package linked to has
> c++ code.
>
> I've put dumb packages to illustrate this emails here ;
> http://addictedtor.free.fr/misc/linkingto
>
> Package A defines this C++ class:
>
> class A {
> public:
> A() ;
> ~A() ;
> SEXP hello() ;
> } ;
>
> Package B has this function :
>
> SEXP say_hello(){
> A a ;
> return a.hello() ;
> }
>
> headers of package A are copied into inst/include so that package B can
> have.
>
> LinkingTo: A
>
> in its DESCRIPTION file.
>
> Also, package B has the R function ;
>
> g <- function(){
> .Call("say_hello", PACKAGE = "B")
> }
>
> With this I can compile A and B, but then I get :
>
> $ Rscript -e "B::g()"
> Error in dyn.load(file, DLLpath = DLLpath, ...) :
> unable to load shared library '/usr/local/lib/R/library/B/libs/B.so':
> /usr/local/lib/R/library/B/libs/B.so: undefined symbol: _ZN1AD1Ev
> Calls: :: ... tryCatch -> tryCatchList -> tryCatchOne -> <Anonymous>
>
> If I then add a Makevars in B with this :
>
>
> # find the root directory where A is installed
> ADIR=$(shell $(R_HOME)/bin/Rscript -e "cat(system.file(package='A'))" )
>
> PKG_LIBS= $(ADIR)/libs/A$(DYLIB_EXT)
>
>
> Then it works:
>
> $ Rscript -e "B::g()"
> [1] "hello"
>
> So it appears that adding the -I flag, which is what LinkingTo does is
> not enough when the package "linking from" (B) actually has to link to
> the "linked to" package (A).
>
> I've been looking at
> http://cran.r-project.org/doc/manuals/R-exts.html#Registering-native-routines
> but it seems only applicable to c(++) functions and not classes ...
>
> What am I missing ? Should/can linkingto be extended in a way that
> accomodates c++
>
> Romain

One other way of course would be to have some lib support, so that for 
example an R library holds not only R packages but shared libraries.

So for example, if as part of package A's Makevars, I copy its A.so into 
R.home( component = "lib" ) and rename it libA.so :

RLIBDIR=$(shell $(R_HOME)/bin/Rscript -e "cat(R.home(component='lib'))" )

all: $(SHLIB) install

install:
	cp $(SHLIB) $(RLIBDIR)/lib$(SHLIB)
	cp -f A.h ../inst/include

Then B can just have this Makevars :

PKG_LIBS=-lA

as well as the "LinkingTo: A" in the description.

Now I realize that R.home(component='lib') is not the right place where 
to host libA.so, as one might not have rights, etc ... but should there 
be a right place, as a per-R-library lib folder ?

Romain

-- 
Romain Francois
Professional R Enthusiast
+33(0) 6 28 91 30 30
http://romainfrancois.blog.free.fr
|- http://tr.im/NrTG : Rcpp 0.7.5
|- http://tr.im/MPYc : RProtoBuf: protocol buffers for R
`- http://tr.im/KfKn : Rcpp 0.7.2



[Rd] LinkingTo and C++
Romain Francois