2013-01-11 12 views
12

Attualmente ho un file .cpp che posso compilare utilizzando sourceCpp(). Come previsto, la funzione R corrispondente viene creata e il codice funziona come previsto.Spostamento da sourceCpp a un pacchetto w/Rcpp

Eccolo:

#include <Rcpp.h> 
using namespace Rcpp; 

// [[Rcpp::export]] 
NumericVector exampleOne(NumericVector vectorOne, NumericVector vectorTwo){ 

    NumericVector outputVector = vectorOne + vectorTwo; 

    return outputVector; 
} 

ora sto convertendo il mio progetto verso un pacchetto utilizzando Rcpp. Così ho creato lo scheletro con rStudio e ho iniziato a studiare come convertire le cose.

In Hadley di excellent primer on Cpp, dice nella sezione "Utilizzo di Rcpp in un pacchetto":

If your packages uses the Rcpp::export attribute then one additional step in the package build process is requried. The compileAttributes function scans the source files within a package for Rcpp::export attributes and generates the code required to export the functions to R.

You should re-run compileAttributes whenever functions are added, removed, or have their signatures changed. Note that if you build your package using RStudio or devtools then this step occurs automatically.

Quindi sembra che il codice compilato con sourceCpp() dovrebbe funzionare più o meno come è in un pacchetto.

Ho creato il file R corrispondente.

exampleOne <- function(vectorOne, vectorTwo){ 
    outToR <- .Call("exampleOne", vectorOne, vectorTwo, PACKAGE ="testPackage") 
    outToR 
} 

Poi ho (ri) costruito il pacchetto e ottengo questo errore:

Error in .Call("exampleOne", vectorOne, vectorTwo, PACKAGE = "voteR") : C symbol name "exampleOne" not in DLL for package "testPackage"

Qualcuno ha un'idea di che cosa ho bisogno di fare quando prende il codice che compila con sourceCpp() e quindi utilizzarlo in un pacchetto?

Vorrei sottolineare che ho letto: "Scrivere un pacchetto che utilizza Rcpp" http://cran.rstudio.com/web/packages/Rcpp/vignettes/Rcpp-package.pdf e capire la struttura di base presentato lì. Tuttavia, dopo aver esaminato il codice sorgente RcppExamples, sembra che la struttura delle vignette non sia esattamente la stessa utilizzata nel pacchetto di esempio. Ad esempio non ci sono file .h usati. Inoltre né la vignetta né il codice sorgente usano l'attributo [[Rcpp :: export]]. Tutto ciò rende difficile rintracciare esattamente dove si trova il mio errore.

+0

Se si utilizza 'compileAttributes' correttamente, non è necessario creare le funzioni R da soli.Ma molto dipende da come si sta creando il pacchetto: gli strumenti di sviluppo del pacchetto in RStudio e in (la versione di sviluppo di) devtools si prenderanno cura della maggior parte dei dettagli per voi. – hadley

+0

Il mio voto è ancora valido per farlo a mano e capire cosa succede --- inizia con 'rcpp.package.skeleton()' che * fa * ha un'opzione per l'uso con Attributi. –

+0

Grazie a tutti e due. Ho scaricato la "mia" versione del file R dopo aver realizzato, proprio come Hadley ha detto, che il file RcppExports.R conteneva tutte le funzioni R corrispondenti (grazie alla ["Attributi" Vignetta] (http: //dirk.eddelbuettel. it/code/rcpp/Rcpp-attributes.pdf.)) L'errore è scomparso ora. Cercando di creare la mia versione del file R è stato in qualche modo avvincente (forse la libreria condivisa?). – politicalEconomist

risposta

2

Ti manca la foresta per gli alberi.

sourceCpp() è una funzione recente; fa parte di ciò che chiamiamo "attributi Rcpp" che ha una sua vignetta (con lo stesso titolo, nel pacchetto, sul mio sito web e su CRAN) che potresti voler leggere. E 'tra l'altro dettagli su come trasformare qualcosa che hai compilato ed eseguito usando sourceCpp() in un pacchetto. Che è quello che vuoi

Passare da una documentazione all'altra non ti aiuterà, e alla fine della documentazione di origine autentica dagli autori dei pacchetti potrebbe essere preferibile. O per fare un giro diverso: stai utilizzando una nuova funzionalità ma una vecchia documentazione che non la riflette. Prova a scrivere un pacchetto base con Rcpp, cioè vieni anche dall'altra parte.

Infine, v'è una mailing list ...

8

Ecco il mio "passeggiata" di come andare da utilizzare sourceCpp() per un pacchetto che utilizza Rcpp. Se c'è un errore non esitare a modificare questo o fammi sapere e io lo modificherò.

[NOTA: vi consiglio vivamente di utilizzare RStudio per questo processo.]

in modo da avere la cosa sourceCpp() giù pat e ora è necessario creare un pacchetto.Questo non è difficile, ma può essere un po 'complicato, perché le informazioni là fuori sulla creazione di pacchetti con Rcpp vanno dalla esauriente documentazione completa che desideri con qualsiasi pacchetto R (ma che è sopra la tua testa come un principiante), e il newbie sensibile introduzioni (che potrebbero tralasciare un dettaglio di cui hai bisogno).

Qui utilizzo oneCpp.cpp e twoCpp.cpp come i nomi di due file .cpp che verranno utilizzati nel pacchetto.

Ecco cosa suggerisco:

R. Per prima cosa si supponga di avere una versione di theCppFile.cpp che compila con sourceCpp() e funziona come ci si aspetta che. Questo non è un must, ma se sei nuovo ai pacchetti Rcpp OR, è bello assicurarsi che il tuo codice funzioni in questa semplice situazione prima di passare al caso più complicato di seguito.

B. Ora creare il pacchetto utilizzando Rcpp.package.skeleton() o utilizzare il progetto> Crea progetto> Pacchetto w/procedura guidata Rcpp in RStudio (altamente consigliato). È possibile trovare dettagli sull'utilizzo di Rcpp.package.skeleton() in [hadley/devtools] [1] o [Scenario attributi Rcpp] [2]. La documentazione completa per scrivere pacchetti con Rcpp è in [Scrivere un pacchetto che usi Rcpp] [3], tuttavia questo presuppone che tu conosca abbastanza bene il tuo modo di usare C++, e non usi il nuovo modo "Attributi" di fare Rcpp. Sarà inestimabile se ci si muove verso la creazione di pacchetti più complessi.

Ora si dovrebbe avere una struttura di directory per il pacchetto che sembra qualcosa di simile:

yourPackageName 
- DESCRIPTION 
- NAMESPACE 
- \R\ 
    - RcppExports.R 
- Read-and-delete-me 
- \man\ 
    - yourPackageName-package.Rd 
- \src\ 
    - Makevars 
    - Makevars.win 
    - oneCpp.cpp 
    - twoCpp.cpp 
    - RcppExports.cpp 

Una volta che tutto è impostato, non un "Build & Reload" se si utilizza RStudio, o compileAttributes() se non si è in RStudio.

C. Ora si dovrebbe vedere nella directory \ R un file denominato RcppExports.R. Aprilo e dai un'occhiata. In RcppExports.R dovresti vedere le funzioni wrapper R per tutti i file .cpp che hai nella directory \src. Abbastanza dolce, eh ?.

D) Provare la funzione R che corrisponde alla funzione scritta in theCppFile.cpp. Funziona? Se è così vai avanti

E) È ora possibile aggiungere nuovi file .cpp come otherCpp.cpp alla directory \src durante la creazione. Quindi devi solo ricostruire il pacchetto e i wrapper R verranno generati e aggiunti a RcppExports.R per te. In RStudio questo è solo "Build & Ricarica" ​​nel menu Genera. Se non si utilizza RStudio, è necessario eseguire compileAttributes()

4

In breve, il trucco è chiamare compileAttributes() dalla radice del pacchetto. Così, per esempio per il pacchetto foo

$ cd /path/to/foo 
$ ls 
DESCRIPTION man NAMESPACE R src 
$ R 
R> compileAttributes() 

Questo comando genererà il RcppExports.cpp e RcppExports.R che mancavano.

0

Ho modificato l'eco politico e le risposte di Calimo ai codici che creano un pacchetto da un semplice file Rcpp.

package_name = "abc" 
fpath_cpp_func = "C:/temp/cppfile.cpp" #a file generates no errors in soruceCpp(fpath_cpp_func) 
path_build = "c:/r/rtoolbox" 
r_exe = "C:/r/r-3.3.1/bin/r.exe" 


#convert one file Rcpp .cpp file to a package 
require(Rcpp) 

setwd(path_build) 

#create package skeleton , new folder 
Rcpp.package.skeleton(package_name) 

#copy cpp file to src/ 
file.copy(fpath_cpp_func , file.path(package_name,"src")) 

#copy other R codes to R/ (optional) 
#file.copy(fpath_R_func, file.path(package_name,"R")) 

#compileAttributes() 
compileAttributes(pkgdir = package_name) 

#to generate manual, edit .Rd files in man/ 

#build, create 'abc_1.0.tar.gz' 
cmd = paste0('"' ,r_exe, '"', " CMD build ", package_name) 
shell(cmd) 

#check, 
#cmd_check = paste0('"' ,r_exe, '"', " CMD check ", package_name)    #to generate manual 
cmd_check = paste0('"' ,r_exe, '"', " CMD check ", package_name, " --no-manual") #no manual 
shell(cmd_check) 

#install 
install.packages(paste0(package_name, "_1.0.tar.gz")) 

#load package 
#require(package_name, character.only=TRUE) 
+0

Non sei sicuro del perché aggiorni una quindicina di quesiti_ quando avevamo _diverse dozzine di rilasci da allora_ con miglioramenti marcati al codice e alla documentazione. –

+0

@dirk È molto importante imparare a creare e documentare un pacchetto. Credo sinceramente che molte persone creino pacchetti solo per saltare il tempo necessario per compilare in 'sourceCpp'. – user3226167

Problemi correlati