Skip to content

problems linking c++ code

4 messages · Allan Strand, Brian Ripley

#
I've been trying to learn about dynamically loading subroutines in R.
Ultimately I would like to use this approach to implement some
simulations.  For the moment though, I've run into a problem compiling
c++ code and loading it into R.

The 'C/C++' and 'R'code below works fine when compiled and linked with
gcc, but gives an error when the library is compiled and linked with
g++.  In the case when it fails, it does so because of an undefined
symbol in the *.so file.  Is there something I can link in to resolve
this problem?  Is there another obvious solution?

The system is FreeBSD 4.x-stable.  The R version is 1.3.1. The gcc/g++
version is 2.95.3.  I compile with R CMD INSTALL and my MAkevars file
has the following lines:

PKG_CXXFLAGS = -fPIC -I./ -I../../ 
PKG_CFLAGS = -fPIC -I./ -I../../ 
PKG_LIBS = -L/usr/local/lib 
 

The error I get when loading the library in R is:
Error in dyn.load(x, as.logical(local), as.logical(now)) : 
        unable to load shared library "/usr/local/lib/R/library/rmetasim/libs/rmetasim.so":
  /usr/local/lib/R/library/rmetasim/libs/rmetasim.so: Undefined symbol "Rf_unprotect__Fi"
Error in library(rmetasim) : .First.lib failed
R-code
=====================

.First.lib <- function(libpath, libname)
  {
    library.dynam(libname)
  }

read.landscape <- function(fn = "filename")
  {
    .Call("read_landscape",fn,PACKAGE = "rmetasim")
  }

C-code
===================
#include <R.h>
#include <Rdefines.h>
#include <Rinternals.h>

#ifdef __cplusplus
extern "C" SEXP read_landscape(SEXP fn);
extern "C" {
#endif

SEXP read_landscape(SEXP fn)
{
  SEXP l;
  PROTECT(l = allocVector (REALSXP, 2));
  REAL(l)[0] = 12.0;
  REAL(l)[1] =14.5;
  UNPROTECT(1);
  return l;
}

#ifdef __cplusplus
} ///end of extern "C"
#endif
#
On 9 Sep 2001, Allan Strand wrote:

            
Using the Rinternals.h in C++ code is not supported.
It's not clear to me why you are writing C in C++ inside extern "C"
declarations, but if you do you need to put
the Rinternals.h inside extern "C" too.

BTW, you code is not using Rdefines.h, but I think that may need to be
inside extern "C" too.

The `standard' headers (those used with .C) have extern "C" wrappers, but
not the advanced ones for .Call/.Extern.  We assume that people using
.Call are pretty au fait with their ccompiler systems, and already know
how to use .C.
That should be library.dynam("rmetasim", libname, libpath) to make sure
you use your package.

  
    
#
Prof Brian Ripley <ripley at stats.ox.ac.uk> writes:
That certainly fixes the problem I posted.

I had c++ code inside the extern "C" {} as well.  The simulation
library I have already written is in c++.  I tried to pare down the
code to the smallest functioning bit that still exhibited the
behavior.  I didn't want to post a more extraneous code than
necessary.  Ultimately, I'd like to instantiate a c++ object and
convert it into several R objects.
It was using Rdefines.h, but I went to the Rinternals solution while
exploring my problem.
Clumsily trying to develop such an expertise...

Do you know of examples of c++ code interfaced through the
.Call/.Extern system?

Thanks for your pointers,
a.
#
On 10 Sep 2001, Allan Strand wrote:
....
The Matrix library on CRAN, for one.  Most people seem to use the R
internals in C and link to other C++ functions through extern "C" exports.

Matrix has

extern "C" {
#include <R.h>
#include <Rinternals.h>
...
}