2

I'm using Rcpp to get self-written C++ into R.

I have the 3 follwing C++ files

header.h

#include <Rcpp.h>
int x();

def.cpp

#include <Rcpp.h>
#include "header.h"
// [[Rcpp::export]]
int x()
{
  return 0;
}

call.cpp

#include <Rcpp.h>
#include "header.h"

// [[Rcpp::export]]
int callx(){
  return x();
}

After compiling successfully I can call the function callx() as well as x() from R

R> callx()
[1] 0
R> x()
[1] 0

But when I try to source the file call.cpp using cppSource I get this error

> Rcpp::sourceCpp('src/call.cpp')
Error in dyn.load("/tmp/RtmpNpOnpJ/sourceCpp-x86_64-pc-linux-gnu-0.12.16/sourcecpp_3a47f828d0d/sourceCpp_2.so") :
unable to load shared object '/tmp/RtmpNpOnpJ/sourceCpp-x86_64-pc-linux-gnu-0.12.16/sourcecpp_3a47f828d0d/sourceCpp_2.so':
/tmp/RtmpNpOnpJ/sourceCpp-x86_64-pc-linux-gnu
0.12.16/sourcecpp_3a47f828d0d/sourceCpp_2.so: undefined symbol: _Z1xv

For compiling I use R CMD INSTALL which includes the follwing steps:

g++  -I/usr/share/R/include -DNDEBUG  -I"/usr/lib/R/library/Rcpp/include"    -fpic  -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g  -c RcppExports.cpp -o RcppExports.o
g++  -I/usr/share/R/include -DNDEBUG  -I"/usr/lib/R/library/Rcpp/include"    -fpic  -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g  -c call.cpp -o call.o
g++  -I/usr/share/R/include -DNDEBUG  -I"/usr/lib/R/library/Rcpp/include"    -fpic  -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g  -c def.cpp -o def.o
g++ -shared -L/usr/lib/R/lib -Wl,-Bsymbolic-functions -Wl,-z,relro -o linkingtest.so RcppExports.o call.o def.o -L/usr/lib/R/lib -lR
flappix
  • 2,038
  • 17
  • 28

2 Answers2

7

I really do not understand why some folks are so opposed to creating packages.

Here is a quick copy and paste of a screen full of output corresponding to five commands giving me exactly what you wanted with your exact input files.

Five simple steps.

Step One: Create a placeholder package for Rcpp

edd@rob:/tmp/flappix$ Rscript -e 'Rcpp::Rcpp.package.skeleton("stubborn")' 
Creating directories ...                                                                                                                                                                                                   
Creating DESCRIPTION ...                                                                                     
Creating NAMESPACE ...                                 
Creating Read-and-delete-me ...                          
Saving functions and data ...                          
Making help files ...                                                                                                                                                                                                      
Done.                                                                                                        
Further steps are described in './stubborn/Read-and-delete-me'.

Adding Rcpp settings                                                         
 >> added Imports: Rcpp                                                                                                                                                                                                    
 >> added LinkingTo: Rcpp                                                                                    
 >> added useDynLib directive to NAMESPACE            
 >> added importFrom(Rcpp, evalCpp) directive to NAMESPACE
 >> added example src file using Rcpp attributes      
 >> added Rd file for rcpp_hello_world                                                                                                                                                                                     
 >> compiled Rcpp attributes                                                                                 
 edd@rob:/tmp/flappix$

Step Two: Copy your exact three sources files

edd@rob:/tmp/flappix$ cp -vax header.h def.cpp call.cpp stubborn/src/                                        
'header.h' -> 'stubborn/src/header.h'                 
'def.cpp' -> 'stubborn/src/def.cpp'                      
'call.cpp' -> 'stubborn/src/call.cpp'  
edd@rob:/tmp/flappix$

Step Three: Run compileAttributes() to update the exports

edd@rob:/tmp/flappix$ cd stubborn/                         
edd@rob:/tmp/flappix/stubborn$ Rscript -e 'Rcpp::compileAttributes()'
edd@rob:/tmp/flappix$

Step Four: Build the package

edd@rob:/tmp/flappix/stubborn$ R CMD build .             
* checking for file ‘./DESCRIPTION’ ... OK                                                                   
* preparing ‘stubborn’:                                                                                      
* checking DESCRIPTION meta-information ... OK        
* cleaning src                                                                           
* installing the package to process help pages        
* saving partial Rd database                                                                                 
* cleaning src                                        
* checking for LF line-endings in source and make files and shell scripts                                    
* checking for empty or unneeded directories          
* building ‘stubborn_1.0.tar.gz’                                                                             
edd@rob:/tmp/flappix$                                                          

Step Five: Install it

edd@rob:/tmp/flappix/stubborn$ R CMD INSTALL stubborn_1.0.tar.gz
* installing to library ‘/usr/local/lib/R/site-library’
* installing *source* package ‘stubborn’ ...                                                                 
** libs                                               
ccache g++ -I/usr/share/R/include -DNDEBUG  -I"/usr/local/lib/R/site-library/Rcpp/include"    -fpic  -g -O3 -Wall -pipe  -Wno-misleading-indentation -Wno-unused -Wno-ignored-attributes -Wno-deprecated-declarations -marc
h=native -c RcppExports.cpp -o RcppExports.o          
ccache g++ -I/usr/share/R/include -DNDEBUG  -I"/usr/local/lib/R/site-library/Rcpp/include"    -fpic  -g -O3 -Wall -pipe  -Wno-misleading-indentation -Wno-unused -Wno-ignored-attributes -Wno-deprecated-declarations -marc
h=native -c call.cpp -o call.o                                                                 
ccache g++ -I/usr/share/R/include -DNDEBUG  -I"/usr/local/lib/R/site-library/Rcpp/include"    -fpic  -g -O3 -Wall -pipe  -Wno-misleading-indentation -Wno-unused -Wno-ignored-attributes -Wno-deprecated-declarations -marc
h=native -c def.cpp -o def.o                                                          
ccache g++ -I/usr/share/R/include -DNDEBUG  -I"/usr/local/lib/R/site-library/Rcpp/include"    -fpic  -g -O3 -Wall -pipe  -Wno-misleading-indentation -Wno-unused -Wno-ignored-attributes -Wno-deprecated-declarations -marc
h=native -c rcpp_hello_world.cpp -o rcpp_hello_world.o   
ccache g++ -Wl,-S -shared -L/usr/lib/R/lib -Wl,-Bsymbolic-functions -Wl,-z,relro -o stubborn.so RcppExports.o call.o def.o rcpp_hello_world.o -L/usr/lib/R/lib -lR
installing to /usr/local/lib/R/site-library/stubborn/libs                  
** R                                                                                                         
** preparing package for lazy loading                    
** help                                                          
*** installing help indices                           
** building package indices                                                                                  
** testing if installed package can be loaded
* DONE (stubborn)
edd@rob:/tmp/flappix/stubborn$ 

And it obviously loads as it automagically links against all source files in src/.

Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
  • thx, but the problem occurs not by creating the package but at runtime when the sourceCpp line is called. I think, sourceCpp compiles and links the file on its own independet from the package binaries. – flappix May 16 '18 at 08:16
  • Not at all -- the "problem" is that you still misunderstand the use and purpose of `sourceCpp()` which _simply is not meant for the mult-file use_ you insist on trying here. Please spend some time with the very clear and detailed vignette on [Rcpp Attributes](https://cloud.r-project.org/web/packages/Rcpp/vignettes/Rcpp-attributes.pdf) to understand this better. For multiple file, a package must be used. As I showed you, it works automagically and _as is_ if you do. – Dirk Eddelbuettel May 16 '18 at 10:14
2

sourceCpp is meant for single translation units that are compiled and linked, which normally implies individual C++ files. You could use #include def.cpp, but I find that rather odd and would require using a different file than in the package source. However, I am really wondering why you want to source the file when you already build a package out of the set of files.

Ralf Stubner
  • 26,263
  • 3
  • 40
  • 75
  • I've got some code from someone else and also got the task to make it running. It would be nice not to have to rewrite the code – flappix May 15 '18 at 19:41
  • 1
    @flappix You have it working in a package -> mission accomplished. You could try to cobble up something with `R CMD SHLIB`, but that is more complicated and less transparent than a package. – Ralf Stubner May 15 '18 at 19:49
  • In the package there is a R file which uses ```sourceCpp``` to source a C++ file (also in the package). So the package is not working at all. – flappix May 15 '18 at 20:00
  • 1
    @flappix `sourceCpp` cannot be used inside a package! Where did you get that idea and what are you trying to achieve by it? – Ralf Stubner May 15 '18 at 20:01