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