Reputation: 117
What is the most correct way to export some constants from C++ code into R using Rcpp?
I am writing a wrapper for some C library and there are some constants defined in library's headers which may be used in API calls. Since I want to mimic that API as close as possible in R code I'd like to export these constants from C to R.
Upvotes: 2
Views: 372
Reputation: 35314
In Rcpp code you can get access to all the R environments that exist in the running R session as Rcpp Environment
objects. You can then read/write entries through the object.
So what you can do is write an Rcpp function that assigns entries to the constants defined in the underlying header file. Of course, you'll have to include the header file in the compilation of the function in order for it to work.
Example:
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
When the user of your wrapper loads the wrapper, the loading process can both define the Rcpp functions via cppFunction()
calls (to define both the assignConstants()
function and all the actual wrapper functions that do useful things) and then run the assignConstants()
function to actually define the constants in the global environment.
Upvotes: 3
Reputation: 18602
There are probably a couple of ways to do this, but a simple approach would be to export a function that returns a constant value and create an active binding to it. The mechanism would work just as well whether you are using an R function or C/C++ function, and it appears to work even after the underlying function has been removed:
#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
*/
Upvotes: 3