g ++ Rcpp osx上架构x86_64的未定义符号

时间:2016-08-25 05:58:19

标签: macos g++ rcpp

我正在尝试从C ++源文件在OSX El Capitain中创建一个dylib文件,以通过Rcpp读入R。这是我创建的一个非常简单的例子:

//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);
}

当我在我大学可以使用的Linux服务器上使用以下Makefile编译/链接时,

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文件,然后我可以通过dyn.load('test.so')在R会话期间读取该文件。加载后,我可以通过dosum()使用函数dosum(x,y)。大。

但是我想在我的个人Mac上用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上做我在Linux上可以做的事情。我没有理由相信我的Mac上的头文件与Linux盒子上的头文件有根本区别,但我还没有详细检查过。

FWIW,我可以在我的Mac上使用相同的方法创建dylib,只要他们不使用Rcpp(例如,一个简单的cout << "hello world" <<endl;函数),所以也许我的Rcpp安装有些搞砸了。

1 个答案:

答案 0 :(得分:1)

为什么使用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>