c – ‘unlockEnvironment’通过’Rcpp’而不是’inline’实现

实际问题

有人可以让我开始我需要做什么来实现Rcpp下面的unlockEnvironment代码

背景

遇到了这个post并尝试了基于C代码的Winston Chang的解决方inline.它有效,但我觉得我知道太少(实际上没什么,就是)内联或C/C++真的知道我在做什么;-)

所以我认为这将是一个很好的机会,最终开始学习如何使用R作为C和C的接口.而且我想我会跳上Rcpp列车这样做!

温斯顿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
)

重构错误

旁注:当我以某种方式在我的包项目的/ R目录中组织它时,我遇到了Winston代码错误

在大多数情况下使用S4方法,我试图将Winston的代码分解为我放入文件/R / .unlockEnvironment.r的标准R函数.unlockEnvironment().

然后,我将在/R/unlockEnvironment.r中为unlockEnvironment()创建我的S4方法.具有签名env:environment的方法然后将简单地调用.unlockEnvironment(env = env).

设置这样的东西,我最终得到以下错误

Error in .Primitive(“.Call”)(,env) :
NULL value passed as symbol address

如果我将/R/.unlockEnvironment.r目录中的代码放在/R/unlockEnvironment.r中的相应方法中(因此每次调用unlockEnvironment()的相应方法时重新获取内联代码),一切正常很好 – 但由于反复重新采购,效率非常低.

所以我想这必须要么与编写C代码的方式有关,要么与使用inline时组织基于C的函数的方式有关?

解决方法

听起来你的问题基本上等于’我如何使用Rcpp :: attributes’?我建议您查看 Rcpp Gallery中的许多示例以了解更多信息.

主要思路:编写一些C代码,将其放入.cpp文件,然后调用Rcpp :: sourceCpp(< file>)加载它.对于这个特例:

#include <Rcpp.h>
using namespace Rcpp;

/* 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))

// [[Rcpp::export]]
bool unlock_environment(Environment env) {
  UNLOCK_FRAME(env);
  return FRAME_IS_LOCKED(env) == 0;
}

/*** R
env <- new.env()
lockEnvironment(env)
try(env$a <- 1) ## error
unlock_environment(env)
env$a <- 1
*/

在包含这些内容文件调用Rcpp :: sourceCpp()会给我:

> Rcpp::sourceCpp('~/scratch/unlock.cpp')

> env <- new.env()

> lockEnvironment(env)

> try(env$a <- 1) ## error
Error in env$a <- 1 : cannot add bindings to a locked environment

> unlock_environment(env)
[1] TRUE

> env$a <- 1 ## success!

这里的主要小功能

>您可以使用base / STL C类型或Rcpp类型提供签名.请注意,bool是C bool类型,而Environment是包含环境的Rcpp类型.
> Rcpp Attributes处理这些C返回类型到R的SEXP的自动转换.

您可能也喜欢Hadley的adv-r介绍.

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...