2017-01-13 31 views
-1

とCPPのソースをコンパイルしていませんが含ま:Rcpp私はpari.hヘッダファイルとcppのソースを書いたpari.hヘッダ

#include<string> 
#include<vector> 
#include<algorithm> 
#include<cmath> 
#include<stdlib.h> 
#include<time.h> 
#include<iterator> // for ostream_iterator 
#include<strings.h> 
#include<string.h> 
#include<sstream> 
#include <pari/pari.h> // for PARI/GP library 
#include<Rcpp.h> // for sourceCpp to work, this line must be uncommented 

// Enable C++11 via this plugin (Rcpp 0.10.3 or later) 
// [[Rcpp::plugins(cpp11)]] 

using namespace std; 
using namespace Rcpp; // for sourceCpp to work, this line must be uncommented 

// [[Rcpp::export]] 
int main() { 

    long maxp = 1000000; // max value 
    pari_init(500000,2); // initiate pari 
    size_t rsize = 500000; // set stack size variables 
    size_t vsize = 100000000; 

    void paristack_setsize(size_t rsize, size_t vsize); // declare stack function 
    paristack_setsize(rsize, vsize); // set stack size 
    gp_allocatemem(stoi(100000000)); // allocate memory 
    GEN p1; // declare PARI variable 

    p1 = cgetg(maxp, t_VEC); // make the PARI variable a vector 
    long j; // declare the variable for the number to be checked. one above the vector iterator 
    for (long i = 0; i <= maxp; ++i) { // iterate over PARI vector 
     j = i + 1; // decrement index for number 
     gel(p1, i) = sumdiv(stoi(j)); // calculate the sum of divisors and update the vector 
    } 

    vector<long> p2(maxp); // empty vector of native type 
    GEN x; // declare a PARI variable to subset PARI vector 
    for (long i = 0; i < maxp; i++) { // for2, across vector indices 
     x = gel(p1, i); // subset one item of vector 
     p2[i] = gtolong(x); // convert PARI to native long integer and update long vector item 
    } // close for2 

    for (long z = 0; z < maxp; z++) { // for3, to iterate for stdout 
     cout << p2[z] << '\n'; // return the result. the vector items are printed separately 
    } // close for3 

} // close function 

は(不必要なヘッダがあるかもしれない、ということに注意してください、私は通常、それらのすべてをコピーしますソース間で問題はありません)。 pari.hヘッダを持たない同様のソースファイルは、必要な部分(ヘッダー、名前空間、エクスポート行など)を含むRcppでコンパイルします。

ソースRcpp関連​​の参照がコメントしているとき、うまくコンパイルおよびグラムと直接コンパイルすると、次のフラグと++は問題なく動作します。私もRにそれらのフラグを輸入し

g++ -lpari -fpermissive -Wall -Wextra -lm -fno-strict-aliasing -fomit-frame-pointer -o sumdivisors.o sumdivisors.cpp 

Sys.setenv("PKG_CXXFLAGS"="-lpari -fpermissive -Wall -Wextra -lm -fno-strict-aliasing -fomit-frame-pointer") 

/usr/local/lib64/R/library/Rcpp/include/からpariディレクトリのシンボリックリンクも作成しました。

sourceCppコマンドからの出力のようなあるが:

> sourceCpp("sumdivisors.cpp") 
In file included from /usr/local/lib64/R/library/Rcpp/include/Rcpp/r/headers.h:48:0, 
       from /usr/local/lib64/R/library/Rcpp/include/RcppCommon.h:29, 
       from /usr/local/lib64/R/library/Rcpp/include/Rcpp.h:27, 
       from sumdivisors.cpp:15: 
/usr/local/lib64/R/library/Rcpp/include/Rcpp/platform/compiler.h:47:0: warning: "GCC_VERSION" redefined 
    #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)                          

In file included from /usr/local/lib64/R/library/Rcpp/include/pari/pari.h:16:0, 
       from sumdivisors.cpp:14: 
/usr/local/lib64/R/library/Rcpp/include/pari/paricfg.h:19:0: note: this is the location of the previous definition 
#define GCC_VERSION "gcc version 6.2.1 20160830 (GCC)"                                  

Error in dyn.load("/tmp/Rtmpc9edZe/sourceCpp-x86_64-pc-linux-gnu-0.12.8/sourcecpp_188e46b44088/sourceCpp_2.so") :                    
    unable to load shared object '/tmp/Rtmpc9edZe/sourceCpp-x86_64-pc-linux-gnu-0.12.8/sourcecpp_188e46b44088/sourceCpp_2.so':                 
    /tmp/Rtmpc9edZe/sourceCpp-x86_64-pc-linux-gnu-0.12.8/sourcecpp_188e46b44088/sourceCpp_2.so: undefined symbol: pari_mainstack 

IはまたはC++ 11ラインを有効を含まないステップを複製、何も変化しません。私はgccフラグも変更しますが、結果はありません。 gccのバージョン定義とpari_mainstackの定義に問題があるようです。

私はこの問題はソースがどのように書かれているのではないと信じています。下の2つの例の下では、上記のcppコードはベクトルを返すものに変換され、その関数はmainではありません。 Rcppでコンパイルする同様の簡単なコードも表示されます。

#include<stdio.h> 
#include<numeric> // for "accumulate" 
#include<iostream> 
#include<string> 
#include<vector> 
#include<algorithm> 
#include<cmath> 
#include<stdlib.h> 
#include<time.h> 
#include<iterator> // for ostream_iterator 
#include<strings.h> 
#include<string.h> 
#include<sstream> 
#include <pari/pari.h> // for PARI/GP library 
#include<Rcpp.h> // for sourceCpp to work, this line must be uncommented 

// Enable C++11 via this plugin (Rcpp 0.10.3 or later) 
// [[Rcpp::plugins(cpp11)]] 

using namespace std; 
using namespace Rcpp; // for sourceCpp to work, this line must be uncommented 

// [[Rcpp::export]] 
vector<long> sumdivisors() { 

    long maxp = 1000000; // max value 
    pari_init(500000,2); // initiate pari 
    size_t rsize = 500000; // set stack size variables 
    size_t vsize = 100000000; 

    void paristack_setsize(size_t rsize, size_t vsize); // declare stack function 
    paristack_setsize(rsize, vsize); // set stack size 
    gp_allocatemem(stoi(100000000)); // allocate memory 
    GEN p1; // declare PARI variable 

    p1 = cgetg(maxp, t_VEC); // make the PARI variable a vector 
    long j; // declare the variable for the number to be checked. one above the vector iterator 
    for (long i = 0; i <= maxp; ++i) { // iterate over PARI vector 
     j = i + 1; // decrement index for number 
     gel(p1, i) = sumdiv(stoi(j)); // calculate the sum of divisors and update the vector 
    } 

    vector<long> p2(maxp); // empty vector of native type 
    GEN x; // declare a PARI variable to subset PARI vector 
    for (long i = 0; i < maxp; i++) { // for2, across vector indices 
     x = gel(p1, i); // subset one item of vector 
     p2[i] = gtolong(x); // convert PARI to native long integer and update long vector item 
    } // close for2 

    return(p2); 
    /* 
    for (long z = 0; z < maxp; z++) { // for3, to iterate for stdout 
     cout << p2[z] << '\n'; // return the result. the vector items are printed separately 
    } // close for3 
    */ 

} // close function 

#include<stdio.h> 
#include<iostream> 
#include<string> 
#include<vector> 
#include<algorithm> 
#include<cmath> 
#include<math.h> 
#include<time.h> 
#include<Rcpp.h> 

using namespace std; 
using namespace Rcpp; 

//#include "std_lib_facilities.h" 

// [[Rcpp::export]] 
int pe001Cpp(int x) { // define a function pe001 with one in$teger input 
    int sum35 = 0; // define a scalar for the sum. start value is 0 
    for (int i=1; i<x; ++i) { // for 1 loop for counting up to x 
     if (i % 3 == 0 || i % 5 == 0) { // if 1, divisible by 3 or 5 
      sum35 += i; // update sum 
     } // close if 1 
    } // close for 1 
    return sum35; // return the final value 
} // close function 

// [[Rcpp::export]] 
int pe001Cppb(int x) { // efficient method 
    int sumdivisible(int x, int y); // declare the below function in this scope 
    return sumdivisible(x, 3) + sumdivisible(x, 5) - sumdivisible(x, 15); // return the total sum 
} // close function pe001Cppb 

int sumdivisible(int x, int y) { // sum of terms divisibile by y 
    int ny = floor ((x-1)/y); // number of terms less than x and divisible by y 
    return ny * (ny + 1)/2 * y; // return the sum 
} // close function sumdivisible 

次のように直接コンパイルされたバイナリの実行からのフィルタリングstraceの出力は次のようになります。

open("/usr/lib/libpari-gmp-tls.so.5", O_RDONLY|O_CLOEXEC) = 3 
open("/usr/lib/libstdc++.so.6", O_RDONLY|O_CLOEXEC) = 3 
open("/usr/lib/libm.so.6", O_RDONLY|O_CLOEXEC) = 3 
open("/usr/lib/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 3 
open("/usr/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 
open("/usr/lib/libgmp.so.10", O_RDONLY|O_CLOEXEC) = 3 
open("/usr/lib/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3 
open("/usr/lib/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3 
open("/usr/lib/libnss_compat.so.2", O_RDONLY|O_CLOEXEC) = 3 
open("/usr/lib/libnsl.so.1", O_RDONLY|O_CLOEXEC) = 3 
open("/usr/lib/libnss_nis.so.2", O_RDONLY|O_CLOEXEC) = 3 
open("/usr/lib/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = 3 

我々はここhttps://github.com/rstats-db/RPostgres/issues/80からわかるように、問題が可能にリンクされたライブラリのバージョンが間違ってかもしれシンボリックリンクによって解決される。ですから、Rcppがリンクしようとするライブラリファイルを知る必要があります。

更新:

Scanelf出力は、問題のシンボルは/usr/lib/libpari-gmp-tls.so.2.9.1であることを示しています。 G ++コンパイルされたファイルの

[[email protected] ~]$ scanelf -l -s pari_mainstack | grep pari_mainstack 
ET_DYN pari_mainstack /usr/lib/libpari-gmp-tls.so.2.9.1 

straceの出力は、実行可能ファイルが/usr/lib/libpari-gmp-tls.so.5にリンクされていることを示している自体2.9.1バージョンへのシンボリックリンク:

[[email protected] library]$ strace ./sumdivisors3.o |& grep so | grep -v "No such file" 
execve("./sumdivisors3.o", ["./sumdivisors3.o"], [/* 79 vars */]) = 0 
open("/usr/lib/libpari-gmp-tls.so.5", O_RDONLY|O_CLOEXEC) = 3 
open("/usr/lib/libstdc++.so.6", O_RDONLY|O_CLOEXEC) = 3 
open("/usr/lib/libm.so.6", O_RDONLY|O_CLOEXEC) = 3 
open("/usr/lib/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 3 
open("/usr/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 
open("/usr/lib/libgmp.so.10", O_RDONLY|O_CLOEXEC) = 3 
open("/usr/lib/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3 
open("/usr/lib/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3 
socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3 
socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3 
open("/usr/lib/libnss_compat.so.2", O_RDONLY|O_CLOEXEC) = 3 
open("/usr/lib/libnsl.so.1", O_RDONLY|O_CLOEXEC) = 3 
open("/usr/lib/libnss_nis.so.2", O_RDONLY|O_CLOEXEC) = 3 
open("/usr/lib/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = 3 
次のようにsourceCppコマンドで作成sourceCpp_4.soファイルから

LDDの出力は次のとおりです。

[[email protected] library]$ ldd /tmp/Rtmpau9YqY/sourceCpp-x86_64-pc-linux-gnu-0.12.8/sourcecpp_3a105ad2bdba/sourceCpp_4.so 
     linux-vdso.so.1 (0x00007ffc28f9d000) 
     libR.so => not found 
     libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007f5077111000) 
     libm.so.6 => /usr/lib/libm.so.6 (0x00007f5076e0d000) 
     libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x00007f5076bf6000) 
     libc.so.6 => /usr/lib/libc.so.6 (0x00007f5076858000) 
     /usr/lib64/ld-linux-x86-64.so.2 (0x0000564489276000) 

私はLDDと、すべてのこれらのファイルを追跡して、/ usr/libに/ libpari-GMP-TLSへのリンクはありません。 so.2.9.1または/ usr/lib/libpari-gmp-tls .so.5ライブラリ。だから問題は、なぜ必要なヘッダーが含まれている(そしてg ++ができるうちに)sourceCppがそれらのファイルにリンクできないのかということです。

更新:sourceCppの

冗長出力は、次のコマンドを示しています。

Sys.setenv("PKG_CXXFLAGS"="-lpari") 

gp2c出力によれば、:

g++ -I/usr/local/lib64/R/include -DNDEBUG -I/usr/local/include -I"/usr/local/lib64/R/library/Rcpp/include" -I"/home/s/codes/cpp/projecteuler/library" -lpari -fpic -g -O2 -c sumdivisors2.cpp -o sumdivisors2.o 
g++ -shared -L/usr/local/lib64/R/lib -L/usr/local/lib64 -o sourceCpp_5.so sumdivisors2.o -L/usr/local/lib64/R/lib -lR 

を私は(実際に-lpariで十分でフラグを設定しました-lpariフラグもリンクステージに含まれていなければなりませんが、ここでリンクコマンドにはそれがありません。問題の原因になりますか?それとも、なぜsourceCpp_5.soファイルi必要なパリライブラリにリンクされていませんか?

そしてフィナーレ:

リンクのための依存ライブラリはまた、明示的で宣言する必要があります。

Sys.setenv( "PKG_LIBS" = " - LM -lpari -lc")

ライブラリフラグはgp2cの出力で与えられます。 gccバージョンの問題を解決する方法として、オリジナルのpariヘッダディレクトリへのシンボリックリンクを作成する代わりに、Rライブラリパスの中にコピーを作成し、行をコメントアウトしました:

// #define GCC_VERSION "gcc version 6.2。 1 20160830(GCC) "

コンパイルは成功しました。Rは、Rcppのおかげで、Rでの理論計算のPARI/GP速度を楽しむことができます! pari.hヘッダ無し

+0

主な問題は 'undefined symbol:pari_mainstack'ですか?正しい? – coatless

+1

また、これはRcppのバグではありません。公式のバグトラッカーに投稿してから数分後に投稿するのは非常に悪いスタイルです。 – coatless

+0

Rcppのバグでない場合、なぜg ++でコンパイルできますか? –

答えて

4

同様ソースファイル必要な部品とRcppとよくコンパイル(例えば等ヘッダ、名前空間、輸出ラインなど)が含ま

sourceCpp()を使用する場合、一般的なユースケースはありませんではないは、pariのようなシステムインストールライブラリを使用して、が適切なリンクフラグを以前に設定したRパッケージをタップすることを伴います。その結果、別のパッケージはRセッションにpariの浮上を処理し、続いて適切なリンクステートメントを設定するためにヘッダファイルの後ろに// [[Rcpp::depends(pkgname)]]が含まれるようにRcppプラグインマネージャ用のプラグインを登録します。

これを言って、Rcppで動作するようにpariを得るに向かって第一ステップRcppGSLの型であることが好ましいRcppPariパッケージを確立することです。そうするには

、あなたはおそらく必要があります

  • configure.ac:など、例えばコンパイラが有効である(ライブラリは、ユーザーのシステム上存在しないと、システム構成が適していることを確認するには。)
  • src/Makevars.in:コードパッケージに埋め込みの両方コンパイルされるべきであり、の連結方法を処理するために、適切なプリプロセッサフ​​ラグを設定します。 (リンクについては下記をご覧ください。)
  • r/inline.RsourceCpp()cppFunction()(上記の「理想的な」解決策として)を使用するための足場をセットアップするために必要なプラグインを確立する。

私はLDDと、すべてのこれらのファイルを追跡し、/usr/lib/libpari-gmp-tls.so.2.9.1または/usr/lib/libpari-gmp-tls.soへのリンクはありません.5ライブラリ。だから問題は、なぜ必要なヘッダーが含まれている(そしてg ++ができるうちに)sourceCppがそれらのファイルにリンクできないのかということです。あなたが見つけたとおり、PKG_CXXFLAGS-lm -lpari -lcの使用は適切リンク段階中に呼び出されていない

。代わりに、フラグはPKG_LIBオプションで設定する必要がありました。コメントは@jtillyによって強調されました。

パッケージを書くに飛び込む前に、あなたはMakevarsファイルに関してRでプリプロセッサフ​​ラグの背後に異なる意味を見たいと思うかもしれません:だから、

関連する問題