经过一番搜索,我终于在thread 中找到了答案。我想我错过了它,因为它详细说明的解决方案已移至标题为 development 的 wiki 页面,其中内容专门针对希望为 TMB 开发做出贡献的用户,而我只想分发代码其中包含 TMB。
总而言之,该线程建议我采用这样的一些更改(myPkg 应该是您的包的名称):
src/
- 将
.cpp 模板放入mypkg/src。然后,当您构建包时,R 会自动编译它。
说明
将这些行添加到您的描述文件中,以便 R 拥有编译模型模板所需的所有工具。
Depends: TMB, RcppEigen
LinkingTo: TMB, RcppEigen
R/roxygentags.r
现在我们需要将我们的 TMB 模板添加到命名空间文件中。我们可以通过 roxygen 轻松地做到这一点,方法是制作一个像这样的虚拟文件:
#' Roxygen commands
#'
#' @useDynLib myPkg
#'
dummy <- function(){
return(NULL)
}
虚拟函数只是在我的源代码中的某个地方添加标签@useDynLib myPkg 的借口,我不会弄乱它。此标签将使用useDynLib(myPkg)...填充您的NAMESPACE,据我所知,这会在为您加载包时加载共享库。
调用包中的函数:
最后,在调用MakeADFun时,设置DLL="myPkg"。通过此设置,您可以将单个 TMB 模型编译到您的包中。这是因为你的./src/文件夹中编译的内容会根据你的包名自动重命名,所以你不能创建唯一命名的模型。
编辑:分发多个 DLL 的解决方案
经过更多搜索(与上面引用的相同线程)...我意识到官方 wiki 中描述的解决方案(以及上面详细说明)仅与分发单个 dll(即单个 TMB 模型)有关。
如果您想在一个包中分发多个 TMB 模型,您必须使用自己的 makefile。我已经给出了更详细的描述in my blog,所以我将在这里仅简要描述这些步骤,说明它们与我之前描述的步骤有何不同。
src/Makefile
你必须定义你自己的Makefile(或Makefile.win对于windows用户)并将它放到你的src/目录中。这是一个适合我的示例:
all: template1.so template2.so
# Comment here preserves the prior tab
template1.so: template1.cpp
Rscript --vanilla -e "TMB::compile('template1.cpp','-O0 -g')"
template2.so: template2.cpp
Rscript --vanilla -e "TMB::compile('template2.cpp','-O0 -g')"
clean:
rm -rf *o
对于 Windows,将 so 替换为 dll,并使用相关的编译器标志(用于调试)。有关用于调试的编译器标志的信息,请参阅 ?TMB::compile。
R/roxygentags.r
这与上面略有不同:
#' Roxygen commands
#'
#' This is a dummy function who's purpose is to hold the useDynLib roxygen tag.
#' This tag will populate the namespace with compiled c++ functions upon package install.
#'
#' @useDynLib template1
#' @useDynLib template2
#'
dummy <- function(){
return(NULL)
}
使用包中的模型
最后,上述更改将编译多个唯一命名的 TMB 模板并将它们加载到命名空间中。要在包中调用这些模型,下面是一个示例:
obj <- MakeADFun(data = data,
parameters = params,
DLL="template1",
inner.control = list(maxit = 10000),
silent=F)
提示...
当我尝试在 Windows 机器上编译它时遇到了问题……结果证明与未正确清理 src 文件夹有关,并且我将旧的 linux 编译文件卡在了那里。如果您有编译问题,值得手动清除之前构建的 src/ 目录中的残留文件......或者也许有人可以提供一些关于编写更好的 make 文件的好建议!