Actual question
Could someone get me started on what I need to do to implement the code of unlockEnvironment
below in Rcpp?
Background
Came across this post and tried Winston Chang's solution based on C code with inline. It works, but I have the feeling I know too little (practically nothing, that is) about either inline or C/C++ to really know what I'm doing ;-)
So I thought this would be a great opportunity to finally start learning on how to use R as an interface to C and C++. And I think I'd like to hopp on the Rcpp train for doing so!
The code from Winston's Gist
require("inline")
inc <- '
/* This is taken from envir.c in the R 2.15.1 source
https://github.com/SurajGupta/r-source/blob/master/src/main/envir.c
*/
#define FRAME_LOCK_MASK (1<<14)
#define FRAME_IS_LOCKED(e) (ENVFLAGS(e) & FRAME_LOCK_MASK)
#define UNLOCK_FRAME(e) SET_ENVFLAGS(e, ENVFLAGS(e) & (~ FRAME_LOCK_MASK))
'
src <- '
if (TYPEOF(env) == NILSXP)
error("use of NULL environment is defunct");
if (TYPEOF(env) != ENVSXP)
error("not an environment");
UNLOCK_FRAME(env);
// Return TRUE if unlocked; FALSE otherwise
SEXP result = PROTECT( Rf_allocVector(LGLSXP, 1) );
LOGICAL(result)[0] = FRAME_IS_LOCKED(env) == 0;
UNPROTECT(1);
return result;
'
unlockEnvironment <- inline::cfunction(
signature(env = "environment"),
includes = inc,
body = src
)
Refactoring error
On a side note: I ran into an error with Winston's code when I organize it in a certain way in the /R
directory of my package project:
Using S4 methods most of the time, I tried to factor Winston's code out into a standard R function .unlockEnvironment()
that I put into the file /R/.unlockEnvironment.r
I then would create my S4 methods for unlockEnvironment()
in /R/unlockEnvironment.r
. The method with signature env:environment
would then simply call .unlockEnvironment(env = env)
.
Setting up things that way, I end up with the following error:
Error in .Primitive(".Call")(, env) : NULL value passed as symbol address
If I put the code in /R/.unlockEnvironment.r
directory with in the respective method in /R/unlockEnvironment.r
(thus re-sourcing the inline code each time the respective method of unlockEnvironment()
is called), everything works just fine - but it's very inefficient because of the repeated re-sourcing.
So I guess this must have either something to do with the way the C code is written or with the way you need to organize your C-based functions when using inline?
See Question&Answers more detail:os