簡體   English   中英

使用帶有Rcpp的第三方頭文件

[英]Using 3rd party header files with Rcpp

我有一個名為coolStuff.h的頭文件,其中包含我想在我的cpp源文件中使用的函數awesomeSauce(arg1)

目錄結構:

  • 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的軟件包,讓我重新解釋一下這個問題。 我有一個獨立的頭文件coolStuff.h,它包含我想在我的cpp代碼中使用的函數。

1)我應該在包目錄結構中放置coolStuff.h,以便它包含的函數可以被CppFile.cpp使用?

2)如何在cpp文件中調用coolStuff.h? 再次感謝你的幫助。 我從上次談話中學到了很多東西。

注意:我閱讀了小插圖“編寫使用Rcpp的軟件包”,但沒有解釋如何執行此操作。

答案:

好吧,讓我總結一下我的問題的答案,因為它分散在這個頁面上。 如果我得到一個錯誤的細節,請隨時編輯或讓我知道,我將編輯它:

因此,您找到了一個.h.cpp文件,其中包含您要在.cpp文件中使用的函數或其他一些代碼,您要編寫這些文件以與Rcpp一起使用。

讓我們繼續調用這個找到的代碼coolStuff.h並調用你想要使用的函數awesomeSauce() 讓我們調用你正在寫的文件theCppFile.cpp

(我應該注意這里.h文件和.cpp文件中的代碼都是C ++代碼,它們之間的區別在於C ++程序員以正確的方式保持組織。我將在這里討論差異,但在SO上進行簡單搜索會引導你討論差異。對於你需要使用你發現的代碼的R程序員,沒有真正的區別。)

coolStuff.h 您可以使用像coolStuff.h這樣的文件,只要它不調用其他庫,通過剪切和粘貼到theCppFile.cpp ,或者如果您創建一個包,您可以將文件放在帶有theCppFile.cpp\\src目錄中theCppFile.cpp文件並在你正在編寫的文件的頂部使用#include "coolStuff.h" 后者更靈活,允許您在其他.cpp文件中使用coolStuff.h中的函數。

細節:

1) coolStuff.h不能調用其他庫。 這意味着它不能在頂部包含任何include語句。 如果是這樣,我在下面詳述的內容可能不起作用,並且使用調用其他庫的已找到代碼超出了本答案的范圍。

2)如果要使用sourceCpp()編譯文件, sourceCpp()需要將coolStuff.h剪切並粘貼到theCppFile.cpp 我被告知有異常,但sourceCpp()旨在編譯一個.cpp文件,這是最好的路由。

(注意:我不保證簡單的剪切和粘貼將開箱即用。您可能必須重命名變量,或者更有可能切換所使用的數據類型與您在theCppFile.cpp中使用的數據類型一致。但是到目前為止,使用6種不同的簡單.h文件,剪切和粘貼對我來說很簡單。

3)如果你只需要在theCppFile.cpp使用coolStuff.h中的代碼而coolStuff.h其他地方,那么你應該將它剪切並粘貼到theCppFile.cpp

(我再也不保證看到上面關於剪切和粘貼的說明)

4)如果要在theCppFile.cpp和其他.cpp文件中使用coolStuff.h中包含的代碼,則需要研究構建包。 這並不難,但可能有點棘手,因為有關使用Rcpp構建軟件包的信息范圍從您想要的任何R軟件包的詳盡徹底的文檔(但是作為新手高於您的頭腦),以及新手敏感介紹(可能會遺漏碰巧需要的細節)。

這是我的建議:

A)首先使用theCppFile.cpp中的代碼獲取一個版本的theCppFile.cpp ,並將coolStuff.h剪切並粘貼到使用sourceCpp()編譯的theCppFile.cpp中, sourceCpp()預期工作。 這不是必須的,但是如果您是Rcpp OR軟件包的新手,那么在轉移到下面更復雜的情況之前,確保您的代碼在這種簡單的情況下工作是很好的。

B)現在使用Rcpp.package.skeleton()構建您的包或使用RStudio中的Build功能(強烈推薦)。 您可以在hadley / devtoolsRcpp Attributes Vignette中找到有關使用Rcpp.package.skeleton()詳細信息。 使用Rcpp編寫軟件包的完整文檔位於使用Rcpp編寫軟件包中 ,但是這個文件假定您已經很好地了解了C ++,並且沒有使用新的“屬性”方式來執行Rcpp。

如果您不在RStudio中,如果使用RStudio或compileAttributes() ,請不要忘記“構建和重新加載”。

C)現在您應該在\\ R目錄中看到一個名為RcppExports.R的文件。 打開它並檢查出來。 RcppExports.R您應該看到\\src目錄中所有.cpp文件的R包裝函數。 很甜蜜。

D)嘗試與你在theCppFile.cpp編寫的函數相對應的R函數。 它有用嗎? 如果是這樣的話。

E)使用您的包構建,您可以使用theCppFile.cppcoolStuff.h移動到src文件夾中。

F)現在你可以從theCppFile.cpptheCppFile.cpp (以及你想使用coolStuff.h中的代碼的任何其他.cpp文件)的頂部刪除剪切和粘貼代碼。將#include "coolStuff.h"#include <Rcpp.h> 請注意,ranker.h周圍沒有括號,而是有“”。 當包含用戶提供的本地文件而不是像Rcpp或STL等庫文件時,這是一個C ++約定...

G)現在你必須重建包。 在RStudio中,這只是Build菜單中的“Build&Reload”。 如果你不使用RStudio,你應該運行compileAttributes()

H)現在再次嘗試R功能,就像在步驟D)中那樣,希望它可以工作。

問題是sourceCpp明確設計為只構建一個獨立的源文件。 如果您希望sourceCpp具有依賴關系,那么它們需要是:

  1. 在系統中包含目錄(即/usr/local/lib/usr/lib ); 要么

  2. 在R包中,您在Rcpp::depends屬性中列出

正如Dirk所說,如果你想構建多個源文件,那么你應該考慮使用R包而不是sourceCpp

請注意,如果您正在處理包並在包的src目錄中的文件上執行sourceCpp,它將構建它,就像它在包中一樣(即,您可以包含src目錄或inst / include目錄中的文件)。

通過在調用sourceCpp之前設置兩個環境變量,我能夠鏈接任何庫(在這種情況下為MPFR):

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

第一個變量包含庫頭的路徑。 第二個包括庫二進制文件的路徑及其文件名。 在這種情況下,還需要其他依賴庫。 有關更多詳細信息,請檢查g ++編譯和鏈接標志 通常可以使用pkg-config獲取此信息:

pkg-config --cflags --libs mylib

為了更好地理解,我建議使用帶有詳細輸出的sourceCpp來打印g ++編譯和鏈接命令:

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

在調用sourceCpp之前,我能夠使用R中的以下全局命令鏈接一個boost庫

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

基本上鏡像這篇文章,但使用不同的編譯器選項: http//gallery.rcpp.org/articles/first-steps-with-C++11/

幾件事:

  1. 您的主題中的“第三方標題庫”毫無意義。

  2. 第三方標題可以通過模板化代碼工作,其中只需要標題,即只有一個包含步驟,編譯器會解決問題。

  3. 一旦你需要庫和目標代碼的實際鏈接,除非你通過插件(或sourceCpp給它提供元信息,否則你可能無法使用強大而有用的sourceCpp

  4. 那么在那種情況下,寫一個包。

簡單易用的東西就是Rcpp和新屬性,或舊的內聯和cxxfunction 更為復雜的使用---和外部的庫比較復雜,你需要查閱文檔。 我們為Rcpp添加了幾個小插曲。

尖括號<>適用於系統包含,例如標准庫。

對於您自己項目的本地文件,請使用引號:“”。

此外,如果要將標頭放在不同的目錄中,則應在包含它的源文件的本地指定標頭路徑。

所以對於你的例子,這應該工作:

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

您可以配置搜索路徑,以便可以在不執行此操作的情況下找到該文件,但對於您希望包含在多個項目中的內容,或者希望某人“安裝”,通常只會這樣做。

我們可以通過將路徑寫入.R/Makevars文件的PKG_CXXFLAGS變量中的標頭來添加它,如下所示。 以下是在macOS中添加與Anaconda xtensor安裝的xtensor頭文件的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

這在Windows中對我有用:

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

編輯:實際上,如果你使用Boost Headers,你不需要這個(感謝Ralf Stubner):

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM