2016-08-25 98 views
0

我正在嘗試在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安裝莫名其妙地搞砸了。

回答

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> 
+0

是的,我知道,我可以用cppFunction但我真正的代碼是千行長時間分裂許多不同的文件。它甚至包含Fortran例程。在這種情況下使用cppFunction是否仍然可行?每次程序運行時代碼都需要重新編譯是不是真的? – xbot

+0

簡而言之:構建一個包。你永遠不需要一個Makefile,因爲它很容易出錯。就像你在這裏做的那樣 –

相關問題