问题
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
回答1:
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/
.
回答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.
来源:https://stackoverflow.com/questions/50354302/rcpp-sourcecpp-undefined-symbol