"未从当前命名空间解析"从R

时间:2017-04-27 15:55:02

标签: c r namespaces r-package mgcv

我最近在使用mgcv GAM进行一些计算测试。修改了一些原始功能,并添加了一些功能。为了不破坏兼容性,对于我想要修改的每个函数,我在函数名中创建了一个.zheyuan符号的新版本。例如,使用Sl.fit函数进行惩罚最小二乘拟合,我将得到Sl.fit.zheyuan。我只是收集我写入独立R脚本的所有R函数" zheyuan.R"。通过将此文件添加到mgcv_1.8-17 package sourceR目录中,并将此修改后的包编译为本地路径,我可以加载它以进行测试。

我在添加R例程时没有问题,但在添加C例程时没有。安装修改后的软件包时没有错误,但是当我调用我添加的C例程的R包装函数时,我会在我的问题标题中得到错误。如果您对我的案例感兴趣,可以按照以下步骤重现此类错误。

第1步:下载最新的包源

从上面的链接下载1.8-17版本。在CRAN上发布新的mgcv版本时,此类链接将会死亡。但您可以随时前往mgcv CRAN page下载最新版本。

untar来源。首先,删除文件MD5,以便在编译修改后的版本时不会出现恼人的MD5警告。在下文中,我们将在R目录和src目录中添加新内容。

第2步:创建R脚本

考虑以下R包装函数:

RX <- function (R, X) {
  X <- X + 0
  .Call("C_mgcv_RX", R, X)
  X
  }

创建一个R脚本&#34; zheyuan.R&#34;放置此功能,并将其添加到mgcv/R

第3步:添加C例程

关于矩阵计算的C例程通常在src/mat.c下。因此,让我们在此脚本的末尾添加一个新函数:

void mgcv_RX (SEXP R, SEXP X) {
  int nrowX = nrows(X);
  int ncolX = ncols(X);
  double one = 1.0;
  F77_CALL(dtrmm)("l", "u", "n", "n", &nrowX, &ncolX, &one, REAL(R), &nrowX, REAL(X), &nrowX);
  }

这是一个简单的例程,将上三角矩阵R与矩形矩阵X相乘。输出矩阵将覆盖X。为此目的,将调用Level-3 BLAS dtrmm。我们不需要担心头文件或运行时链接到BLAS库。标题在mat.c中可用,并且链接到BLAS由R管理。

第4步:注册C例程

以上不足。 mgcv中的每个C例程都会出现在三个位置。例如,让我们尝试搜索本机C例程:

grep mgcv_RPPt mgcv/src/*
# mgcv/src/init.c:  {"mgcv_RPPt",(DL_FUNC)&mgcv_RPPt,3},
# mgcv/src/mat.c:void mgcv_RPPt(SEXP a,SEXP r, SEXP NT) {
# mgcv/src/mgcv.h:void mgcv_RPPt(SEXP a,SEXP r, SEXP NT);

我们还需要附加头文件mgcv.h,并在init.c中注册此C例程。

让我们追加

void mgcv_RX (SEXP R, SEXP X);

mgcv.h的末尾,在init.c内,执行:

R_CallMethodDef CallMethods[] = {
  {"mgcv_pmmult2", (DL_FUNC) &mgcv_pmmult2,5},
  {"mgcv_Rpiqr", (DL_FUNC) &mgcv_Rpiqr,5}, 
  {"mgcv_tmm",(DL_FUNC)&mgcv_tmm,5}, 
  {"mgcv_Rpbsi",(DL_FUNC)&mgcv_Rpbsi,2},
  {"mgcv_RPPt",(DL_FUNC)&mgcv_RPPt,3},
  {"mgcv_Rpchol",(DL_FUNC)&mgcv_Rpchol,4},
  {"mgcv_Rpforwardsolve",(DL_FUNC)&mgcv_Rpforwardsolve,3},
  {"mgcv_Rpcross",(DL_FUNC)&mgcv_Rpcross,3},
  {"mgcv_RX",(DL_FUNC)&mgcv_RX,2},  //  we add this line
  {NULL, NULL, 0}
};

第5步:编译并加载

tar修改后的mgcv文件夹转到mgcv.tar.gz

打开一个新的,干净的R会话(可能需要R --vanilla才能启动)。然后指定本地库路径并运行:

path <- getwd()  ## let's just use current working directory
## make sure you move "mgcv.tar.gz" into current working path
install.packages("mgcv.tar.gz", repos = NULL, lib = path)
library(mgcv, lib.loc = path)

第6步:测试并获得错误

R <- matrix(runif(25), 5)
R[lower.tri(R)] <- 0
X <- matrix(runif(25), 5)
mgcv:::RX(R, X)  ## function is not exported, so use `mgcv:::` to find it

# Error in .Call("C_mgcv_RX", R, X) : 
#   "C_mgcv_RX" not resolved from current namespace (mgcv)

有人可以解释为什么以及如何解决这个问题吗?

1 个答案:

答案 0 :(得分:1)

我现在有一个临时的“修复”。而不是

.Call("C_mgcv_RX", R, X)

使用以下任一项:

.Call(mgcv:::"C_mgcv_RX", R, X)
.Call(getNativeSymbolInfo("mgcv_RX"), R, X)

我之所以这样,是因为我突然意识到C例程也可以由:::提取出来。由于包编译成功,mgcv:::无法找到此C例程。是的,它有效。

要检查我们定义的C例程在加载的共享库中是否可用,请尝试

is.loaded("mgcv_RX")
# TRUE

要列出已加载的共享库中所有已注册的C例程,请使用

getDLLRegisteredRoutines("mgcv")