g ++ Rcpp osx上未定义的体系结构x86_64符号
问题描述:
我正在尝试在OSX El Capitain中从C++源文件创建一个dylib文件,以通过Rcpp读入R。下面是我所创建的一个非常简化的例子:g ++ Rcpp osx上未定义的体系结构x86_64符号
//test.cpp
#include <Rcpp.h>
RcppExport SEXP dosum(SEXP _a, SEXP _b){
double a = Rcpp::as<double>(_a);
double b = Rcpp::as<double>(_b);
return Rcpp::wrap(a+b);
}
当我编译使用下面的Makefile一台Linux服务器,提供给我在我的大学上/链接,
CC=g++
# note the use of c++14, used to use c++11
all: test
test :
${CC} -DNDEBUG \
-I. \
-I/usr/share/R/include \
-I/server/linux/lib/R/3.0/x86_64/site-library/Rcpp/include \
-I/usr/share/Rcpp_0.12.3/include \
-fpic -O3 -pipe \
-std=c++1y \
-c test.cpp
${CC} -shared -o test.so test.o
clean:
@find . \(-name "*.o" -o -name "*.so" \) -exec rm {} \;
我获得所需的test.so
文件,然后我可以在R会话期间通过dyn.load('test.so')
读入。一旦它被加载,我可以通过dosum(x,y)
使用功能dosum()
。大。
但我想在我的个人电脑上做OSX El Capitain中的完全相同的事情。我已经尝试了Makefile中的许多变化,而现在使用的,
CC=g++
all: temp
temp:
${CC} \
-I. \
-I/usr/share/R/include \
-I/usr/local/include/Rcpp/Rcpp_0.12.5/inst/include \
-fPIC \
-c temp.cpp
${CC} -dynamiclib *.o -o temp.dylib
clean:
@find . \(-name "*.o" -o -name "*.dylib" \) -exec rm {} \;
当我运行这个Makefile,我得到以下,
g++ \
-I. \
-I/usr/share/R/include \
-I/usr/local/include/Rcpp/Rcpp_0.12.5/inst/include \
-fPIC \
-c temp.cpp
g++ -dynamiclib *.o -o temp.dylib
Undefined symbols for architecture x86_64:
"_REprintf", referenced from:
Rcpp::Rstreambuf<false>::xsputn(char const*, long) in temp.o
Rcpp::Rstreambuf<false>::overflow(int) in temp.o
"_R_FlushConsole", referenced from:
Rcpp::Rstreambuf<true>::sync() in temp.o
Rcpp::Rstreambuf<false>::sync() in temp.o
"_R_GetCCallable", referenced from:
dataptr(SEXPREC*) in temp.o
"_R_NilValue", referenced from:
Rcpp::Rcpp_protect(SEXPREC*) in temp.o
Rcpp::Shield<SEXPREC*>::~Shield() in temp.o
"_Rf_allocVector", referenced from:
SEXPREC* Rcpp::internal::primitive_wrap__impl__cast<double>(double const&, Rcpp::traits::integral_constant<bool, false>) in temp.o
"_Rf_coerceVector", referenced from:
SEXPREC* Rcpp::internal::basic_cast<14>(SEXPREC*) in temp.o
"_Rf_length", referenced from:
double Rcpp::internal::primitive_as<double>(SEXPREC*) in temp.o
"_Rf_protect", referenced from:
Rcpp::Rcpp_protect(SEXPREC*) in temp.o
"_Rf_unprotect", referenced from:
Rcpp::Shield<SEXPREC*>::~Shield() in temp.o
"_Rprintf", referenced from:
Rcpp::Rstreambuf<true>::xsputn(char const*, long) in temp.o
Rcpp::Rstreambuf<true>::overflow(int) in temp.o
"_TYPEOF", referenced from:
SEXPREC* Rcpp::r_cast<14>(SEXPREC*) in temp.o
SEXPREC* Rcpp::internal::basic_cast<14>(SEXPREC*) in temp.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [temp] Error 1
也就是说,看来事情越来越乱码在所讨论的变量的前面添加了一个下划线。我究竟做错了什么?我曾尝试添加/删除各种标志,如-fpic
,-std=XXX
等。
我发现了相关的问题,但它们似乎是原始海报首先混淆了如何使用Rcpp的情况。在这里,我只想在Mac上做我能做的事。我没有理由相信我的Mac上的头文件与Linux上的头文件有根本的区别,但我还没有详细检查过。
FWIW,我可以,只要它们不使用RCPP(例如,一个简单的cout << "hello world" <<endl;
功能)创建使用我的Mac同样的方法dylibs,所以也许我RCPP安装莫名其妙地搞砸了。
答
为什么使用Makefile
?
这一切都有效,如果你让R做生意。这里是一到四衬垫(取决于你如何计算):但是
R> cppFunction("SEXP dosum(SEXP a_, SEXP b_){
double a = Rcpp::as<double>(a_);
double b = Rcpp::as<double>(b_);
return Rcpp::wrap(a+b);
}")
R> dosum(4, 7)
[1] 11
R>
注意的是,我不得不恢复你的无效标识_a, _b
为有效a_, b_
。
这一切都可以当然也有给出一个班轮的模板转换,我们免费获得的:
R> cppFunction("double dosum2(double a, double b) { return a+b; }")
R> dosum2(5, 8)
[1] 13
R>
是的,我知道,我可以用cppFunction但我真正的代码是千行长时间分裂许多不同的文件。它甚至包含Fortran例程。在这种情况下使用cppFunction是否仍然可行?每次程序运行时代码都需要重新编译是不是真的? – xbot
简而言之:构建一个包。你永远不需要一个Makefile,因为它很容易出错。就像你在这里做的那样 –