web-dev-qa-db-ja.com

Rcppでサードパーティのヘッダーファイルを使用する

Cppソースファイルで使用したい関数awesomeSauce(arg1)を含むcoolStuff.hというヘッダーファイルがあります。

ディレクトリ構造:

  • RworkingDirectory
    • sourceCpp
      • theCppFile.cpp
    • cppHeaders
      • coolStuff.h

コード:

#include <Rcpp.h>
#include <cppHeaders/coolStuff.h>
using namespace Rcpp;

// [[Rcpp::export]]
double someFunctionCpp(double someInput){

 double someOutput = awesomeSauce(someInput);

return someOutput;
}

エラーが発生します:

 theCppFile.cpp:2:31: error: cppHeaders/coolStuff.h: No such file or directory

ファイルとディレクトリをあちこちに移動しましたが、これを機能させることができないようです。サードパーティのヘッダーを使用する場所のいたるところに、次のような例があります。

#include <boost/array.hpp>

(Hadley/devtoolsからのもの)

https://github.com/hadley/devtools/wiki/Rcpp

では、何が得られるのでしょうか?私は午前中ずっと検索していて、単純なことのように思えるものに対する答えを見つけることができません。

更新01.11.12

RstudioでRcppを使用するパッケージを構築する方法がわかったので、質問を言い換えます。 cppコードで使用したい関数を含むスタンドアロンのヘッダーファイルcoolStuff.hがあります。

1)coolStuff.hをパッケージディレクトリ構造のどこに配置すれば、そこに含まれる関数をCppFile.cppで使用できるようになりますか?

2)cppファイルでcoolStuff.hを呼び出すにはどうすればよいですか?よろしくお願いします。前回の会話から多くのことを学びました。

注:「Rcppを使用するパッケージの作成」というビネットを読みましたが、その方法については説明されていません。

答え:

このページに散らばっているので、私の質問に対する答えを要約しましょう。詳細が間違っている場合は、これを編集するか、私に知らせてください。編集します:

そのため、Rcppで使用するために作成している.hファイルで使用する関数またはその他のコードを含む.cppまたは.cppファイルが見つかりました。

この見つかったコードをcoolStuff.hと呼び続け、使用したい関数をawesomeSauce()と呼びましょう。あなたが書いているファイルをtheCppFile.cppと呼びましょう。

(ここで、.hファイルと.cppファイルのコードはすべてC++コードであり、それらの違いは、C++プログラマーが適切な方法で整理されていることです。違いについてはここで説明します。 、ただし、ここでSOを検索すると、違いについて説明できます。見つけたコードを少し使用する必要があるRプログラマーにとって、実際の違いはありません。)

IN SHORT:coolStuff.hにカットアンドペーストするか、または作成した場合、他のライブラリを呼び出さない限り、theCppFile.cppのようなファイルを使用できます。パッケージでは、ファイルを\srcファイルとともにtheCppFile.cppディレクトリに配置し、書き込んでいるファイルの先頭で#include "coolStuff.h"を使用できます。後者はより柔軟性があり、他のcoolStuff.hファイルの.cppの関数を使用できます。

詳細:

1)coolStuff.hは他のライブラリを呼び出さないでください。つまり、上部にincludeステートメントを含めることはできません。もしそうなら、私が以下に詳述することはおそらく機能しないでしょう、そして他のライブラリを呼び出す見つかったコードの使用はこの答えの範囲を超えています。

2)sourceCpp()を使用してファイルをコンパイルする場合は、coolStuff.hを切り取ってtheCppFile.cppに貼り付ける必要があります。例外があると言われていますが、sourceCpp()は1つの.cppファイルをコンパイルするように設計されているため、これが最適なルートです。

(注:単純なカットアンドペーストがすぐに機能することを保証するものではありません。変数の名前を変更するか、使用しているデータ型をtheCppFile.cppで使用しているデータ型と一致させるように切り替える必要があります。しかしこれまでのところ、カットアンドペーストは、6つの異なる単純な.hファイルで最小限の手間で機能しました)

3)coolStuff.htheCppFile.cppのコードのみを使用する必要があり、他の場所では使用する必要がない場合は、それを切り取ってtheCppFile.cppに貼り付ける必要があります。

(繰り返しますが、カットアンドペーストに関する上記の注を参照してください)

4)coolStuff.hおよびその他のtheCppFile.cppファイルの.cppに含まれるコードを使用する場合は、パッケージの構築を検討する必要があります。これは難しいことではありませんが、Rcppを使用したパッケージの構築に関する情報は、Rパッケージで必要な徹底的なドキュメント(ただし、初心者としては頭上にあります)から、初心者に敏感なものまでさまざまであるため、少し注意が必要です。紹介(詳細が省略されている可能性がありますあなたがたまたま必要とします)。

これが私が提案するものです:

A)まず、theCppFile.cppからcoolStuff.hにカットアンドペーストして、sourceCpp()でコンパイルし、期待どおりに機能するコードを含むtheCppFile.cppのバージョンを取得します。これは必須ではありませんが、Rcpp ORパッケージを初めて使用する場合は、以下のより複雑なケースに進む前に、コードがこの単純な状況で機能することを確認してください。

B)Rcpp.package.skeleton()を使用してパッケージをビルドするか、RStudioのビルド機能を使用します(強くお勧めします)。 Rcpp.package.skeleton()の使用に関する詳細は、 hadley/devtools または Rcpp attributes Vignette にあります。 Rcppを使用してパッケージを作成するための完全なドキュメントは Rcppを使用するパッケージの作成 にありますが、これはC++の使い方をかなりよく知っていることを前提としており、新しい「属性」の方法を使用していません。 Rcpp。

RStudioを使用している場合は「ビルドとリロード」を、RStudioを使用していない場合はcompileAttributes()を忘れないでください。

C)これで、\ RディレクトリにRcppExports.Rというファイルが表示されます。それを開いてチェックしてください。 RcppExports.Rには、\srcディレクトリにあるすべての.cppファイルのRラッパー関数が表示されます。かなり甘い。

D)theCppFile.cppで書いた関数に対応するR関数を試してみてください。それは機能しますか?もしそうなら、次に進みます。

E)パッケージをビルドしたら、coolStuff.htheCppFile.cppとともにsrcフォルダーに移動できます。

F)これで、カットアンドペーストコードをtheCppFile.cppから削除し、theCppFile.cpp(およびcoolStuff.hのコードを使用するその他の.cppファイル)の先頭に#include "coolStuff.h"の直後に#include <Rcpp.h>を配置できます。 ranker.hの前後には角かっこがなく、「」があることに注意してください。これは、RcppやSTLなどのライブラリファイルではなく、ユーザーが提供するローカルファイルを含める場合のC++規則です。

G)パッケージを再構築する必要があります。 RStudioでは、これは[ビルド]メニューの[ビルドとリロード]です。 RStudioを使用していない場合は、compileAttributes()を実行する必要があります

H)ステップD)で行ったのと同じように、R関数を再試行します。うまくいけばうまくいきます。

40

問題は、sourceCppが単一のスタンドアロンソースファイルのみをビルドするように明示的に設計されていることです。 sourceCppに依存関係を持たせたい場合は、次のいずれかである必要があります。

  1. システムにディレクトリを含めます(つまり、/usr/local/libまたは/usr/lib)。または

  2. Rcpp::depends属性にリストするRパッケージ内

Dirkが言ったように、複数のソースファイルをビルドしたい場合は、sourceCppではなくRパッケージの使用を検討する必要があります。

パッケージで作業していて、パッケージのsrcディレクトリ内のファイルに対してsourceCppを実行すると、パッケージがビルドされることに注意してくださいあたかもパッケージ内にあります(つまり、srcディレクトリのファイルを含めることができます)またはinst/includeディレクトリ)。

21
jjallaire

SourceCppを呼び出す前に、2つの環境変数を設定することで、任意のライブラリ(この場合はMPFR)をリンクできました。

Sys.setenv("PKG_CXXFLAGS"="-I/usr/include")
Sys.setenv("PKG_LIBS"="-L/usr/lib/x86_64-linux-gnu/ -lm -lmpc -lgmp -lmpfr")

最初の変数には、ライブラリヘッダーのパスが含まれています。 2つ目は、ライブラリバイナリのパスとそのファイル名を含みます。この場合、他の依存ライブラリも必要です。詳細については、g ++のコンパイルとリンクを確認してください flags 。この情報は通常、pkg-configを使用して取得できます。

pkg-config --cflags --libs mylib

理解を深めるために、g ++コンパイルおよびリンクコマンドを出力するために、詳細な出力でsourceCppを使用することをお勧めします。

sourceCpp("mysource.cpp", verbose=TRUE, rebuild=TRUE)
7
B0RJA

SourceCppを呼び出す前に、Rで次のグローバルコマンドを使用してブーストライブラリをリンクすることができました

Sys.setenv("PKG_CXXFLAGS"="-I \path-to-boost\")

基本的にこの投稿をミラーリングしますが、コンパイラオプションが異なります: http://gallery.rcpp.org/articles/first-steps-with-C++11/

4
statsninja

いくつかのこと:

  1. あなたの主題のような「サードパーティのヘッダーライブラリ」は意味がありません。

  2. サードパーティのヘッダーは、ヘッダーだけが必要なテンプレートコードを介して機能します。つまり、インクルードステップのみがあり、コンパイラーが問題を解決します。

  3. ライブラリとオブジェクトコードの実際のリンクが必要になると、プラグイン(またはenv。vars)を介してメタ情報を提供しない限り、強力で便利なsourceCppを使用できない場合があります。

  4. その場合は、パッケージを作成してください。

簡単で単純なことは、Rcppと新しい属性、または古いインラインとcxxfunctionを使用した場合です。より複雑な使用---および外部ライブラリisより複雑な場合は、ドキュメントを参照する必要があります。そのために、Rcppにいくつかのビネットを追加しました。

2

山かっこ<>は、標準ライブラリなどのシステムインクルード用です。

独自のプロジェクトにローカルなファイルの場合は、引用符「」を使用します。

また、ヘッダーを別のディレクトリに配置する場合は、ヘッダーパスをそれを含むソースファイルに対してローカルに指定する必要があります。

したがって、あなたの例では、これは機能するはずです:

#include "../cppHeaders/coolStuff.h"

それを行わなくてもファイルが見つかるように検索パスを構成できますが、通常は、複数のプロジェクトに含めたいもの、または誰かが「インストール」することを期待するものに対してのみ行う価値があります。

1
JasonD

以下に示すように、PKG_CXXFLAGSファイルの.R/Makevars変数のヘッダーにパスを書き込むことで追加できます。以下は、macOSにAnacondaとともにインストールされたxtensorのヘッダーファイルを追加する例です。

⋊> ~ cat ~/.R/Makevars                                                                                                                              
CC=/usr/local/bin/gcc-7
CXX=/usr/local/bin/g++-7
CPLUS_INCLUDE_PATH=/opt/local/include:$CPLUS_INCLUDE_PATH
PKG_CXXFLAGS=-I/Users/kuroyanagi/.pyenv/versions/miniconda3-4.3.30/include
LD_LIBRARY_PATH=/opt/local/lib:$LD_LIBRARY_PATH
CXXFLAGS= -g0 -O3 -Wall
MAKE=make -j4
1
Keiku

これはWindowsで私のために働いた:

Sys.setenv("PKG_CXXFLAGS"='-I"C:/boost/boost_1_66_0"')

編集:ブーストヘッダーを使用する場合、実際にはこれは必要ありません(Ralf Stubnerのおかげで):

// [[Rcpp::depends(BH)]]

0
Simon Woodward