2016-04-21 7 views
0

Was ist der richtige Weg, um einige Konstanten aus C++ Code in R mit Rcpp zu exportieren?Wie Konstanten von C++ in R mit Rcpp zu exportieren

Ich schreibe einen Wrapper für einige C-Bibliothek und es gibt einige Konstanten in den Header der Bibliothek definiert, die in API-Aufrufe verwendet werden können. Da ich diese API so nah wie möglich in R-Code nachahmen möchte, möchte ich diese Konstanten von C nach R exportieren.

+0

Im engeren Sinne könnten Sie sie einfach im R-Code über '.onLoad()' oder '.onAttach()' definieren. Entweder nur in R-Code oder durch Schleifen über Elemente kehrt von C++ über eine Hilfsfunktion zurück. Etwas Automatisiertes zu tun ist schwieriger. Manchmal wollte ich das für 'Enum'-Typen, aber auch keine gute Lösung. –

Antwort

2

In RCPP Code können Sie den Zugriff auf alle bekommen die R-Umgebungen, die in der laufenden R-Sitzung als Rcpp Environment Objekte existieren. Sie können dann Einträge über das Objekt lesen/schreiben.

Sie können also eine Rcpp-Funktion schreiben, die den in der zugrunde liegenden Headerdatei definierten Konstanten Einträge zuweist. Natürlich müssen Sie die Header-Datei in die Kompilierung der Funktion einfügen, damit sie funktioniert.

Beispiel:

library(Rcpp); 
cppFunction(
    includes='#define A 3', ## replace this with includes='#include "someheader.h"' 
    'void assignConstants() { Environment ge = Environment::global_env(); ge["A"] = A; }' 
); 
A; 
## Error: object 'A' not found 
assignConstants(); 
A; 
## [1] 3 

Wenn der Benutzer Ihrer Wrapper den Wrapper lädt, kann der Ladevorgang sowohl definieren die RCPP Funktionen über cppFunction() Anrufe (zu definieren, sowohl die assignConstants() Funktion und alle aktuellen Funktionen Wrapper, tun nützliche Dinge) und führen Sie dann die assignConstants() Funktion, um tatsächlich die Konstanten in der globalen Umgebung zu definieren.

+1

Ich bin nicht sicher, warum dies abgelehnt wurde. Sieht wie einer von vielen möglichen und vernünftigen Annäherungen an mich aus. –

2

Es gibt wahrscheinlich ein paar Möglichkeiten, dies zu tun, aber eine einfache Vorgehensweise wäre zu exportieren eine Funktion, die einen konstanten Wert zurückgibt und eine aktive Bindung an sie erstellt. Der Mechanismus würde funktionieren genauso gut, ob Sie eine R-Funktion oder C/C++ Funktion verwenden, und es scheint auch zu funktionieren, nachdem die zugrunde liegende Funktion entfernt wurde:

#include <Rcpp.h> 

// [[Rcpp::export]] 
double MyConstant() { 
    return 1.54; 
} 

/***R 

MyConstant2 <- function() 1.54 

makeActiveBinding("my_constant", MyConstant, .GlobalEnv) 
makeActiveBinding("my_constant2", MyConstant2, .GlobalEnv) 

my_constant 
#[1] 1.54 

my_constant2 
#[1] 1.54 

inherits(try(my_constant <- 2.5, TRUE), "try-error") 
#[1] TRUE 

inherits(try(my_constant2 <- 2.5, TRUE), "try-error") 
#[1] TRUE 

rm(MyConstant, MyConstant2) 

my_constant 
#[1] 1.54 

my_constant2 
#[1] 1.54 

inherits(try(my_constant <- 2.5, TRUE), "try-error") 
#[1] TRUE 

inherits(try(my_constant2 <- 2.5, TRUE), "try-error") 
#[1] TRUE 

*/ 
+0

Da dies Konstanten sind, ist keine aktive Bindung zum Abrufen des Werts der Konstante erforderlich. Alles, was benötigt wird, ist die Eingabe der Umgebung in den konstanten Wert. Aber es ist eine interessante Idee. – bgoldst

+0

Das stimmt, aber ich habe hauptsächlich die Bindung, um die 'const'-Eigenschaft von' my_constant' zu erhalten (z. B. 'my_constant <- ...' ist ein Fehler), während 'assignConstants(); A <- 5' ist erlaubt. Obwohl OP ein Paket erstellt und die Konstanten exportiert, sollten sie in beiden Fällen vor der Zuweisung geschützt sein. – nrussell