2014-10-27 76 views
2

這對我來說最初看起來是一個簡單的任務,但我無法得到以下工作。我試圖將fortran子例程包裝到Rcpp調用中,以便使用R中的可用函數。我們的目標是將函數合併到一個包中,所以只在特定的* .so文件中使用dyn.load()是不可行的(除非有人能告訴我怎麼做?)。從閱讀類似的帖子,我懷疑在makevars文件中指定標誌可能會解決問題,但提供的信息是非常簡單的here和一些澄清將真誠讚賞。在Rcpp中包裝fortran函數

我已經完成了以下文件,因爲我可以遵循。

  1. Rcpp.package.skeleton
  2. 將在創建的RCPP包裝一個基本的cpp文件(HELLO.CPP)
  3. 創建的src目錄
  4. 創建包結構我Fortran文件(hello.f) R檔來創建一個「乾淨」的函數調用(即避免.Call用戶和前.Call允許運行的其他內部計算)

然而,當我嘗試建立我的包(帶RStudio),我碰到下面的錯誤輸出:

==> R CMD INSTALL --no-multiarch --with-keep.source fortran 

g++ -shared -o fortran.so RcppExports.o hello.o hello.o rcpp_hello_world.o -lgfortran -lm -lquadmath -L/usr/lib/R/lib -lR 
* installing to library ‘/home/.../R/x86_64-pc-linux-gnu-library/3.0’ 
* installing *source* package ‘fortran’ ... 
** libs 
hello.o: In function `hello_wrapper': 
/home/.../r_code/fortran/src/hello.cpp:16: multiple definition of `hello_wrapper' 
hello.o:/home/.../r_code/fortran/src/hello.cpp:16: first defined here 
collect2: error: ld returned 1 exit status 
make: *** [fortran.so] Error 1 
ERROR: compilation failed for package ‘fortran’ 
* removing ‘/home/.../R/x86_64-pc-linux-gnu-library/3.0/fortran’ 

Exited with status 1. 

我的文件如下:

hello.f

subroutine hello() 
    print *, "hello world" 
end subroutine hello 

打招呼。 h

extern "C" 
{ 
    void hello(); 
} 

HELLO.CPP

#include <R.h> 
#include <Rinternals.h> 
#include <Rdefines.h> 

#include "hello.h" 

#ifdef __cplusplus 
extern "C" 
{ 
    SEXP hello_wrapper(); 
} 
#endif 

SEXP 
hello_wrapper() 
{ 
    hello(); 
} 

wrapper.R

hello_r <- function(){ 
    .Call("hello_wrapper"); 
} 

回答

1

我相信這個問題很簡單,因爲當你使用不同的擴展名包含名稱名稱的多個文件時,R會不高興。嘗試將hello.f重命名爲hello_fortran.f,然後從那裏開始。

+0

是的,我也想提出這個建議。除此之外,它應該是微不足道的。 – 2014-10-27 19:44:21

+0

將'hello.f'重命名爲'hello_fortran.f'並將'hello.cpp'重命名爲'hello_cpp.cpp',但是'dyn.load ...中的另一個錯誤...無法加載共享對象/ home/.../fortran.so:undefined symbol:hello' – cdeterman 2014-10-27 19:58:31

+1

@DirkEddelbuettel,我已經瞭解到fortran函數在頭文件中需要一個下劃線,並在cpp文件中調用。完成此操作後,該包會成功建立。我會接受這個答案,因爲它解決了我最初的問題,但同樣感謝你Dirk,我很欣賞你的幫助。 – cdeterman 2014-10-27 20:17:52

1

我認爲,如果你刪除

#ifdef __cplusplus 
extern "C" 
{ 
    SEXP hello_wrapper(); 
} 
#endif 

部分,這可能工作。也看看Rcpp屬性小插曲 - 你不需要手寫wrapper.R

+0

謝謝你的迴應,但是這並沒有解決問題。我仍然有'hello_wrapper()的多重定義的錯誤''我也會研究Rcpp屬性。 – cdeterman 2014-10-27 19:08:35

+0

另外,你是否知道'.Fortran()'?你不必在此涉及Rcpp。但在調用Fortran之前,是否需要/想在C++級別上做一些工作? – 2014-10-27 19:33:37

+0

我知道'。Fortran()'但是是的,我想在某些Fortran調用之前做一些C++。我在其他軟件包中看到了這一點,我試圖用這個簡單的程序進行復制,但遇到這個錯誤。 – cdeterman 2014-10-27 19:38:53

0

Rcpp函數和.Fortran不能同時存在。 只是不包含Fortran函數src/RcppExports.cpp