[英]Rcpp functions undefined when used alongside Stan
I have an R package that uses Rcpp for some internal functions. 我有一个R包,它使用Rcpp来实现一些内部功能。 These functions are not exported for the user to access directly (see minimally reproducible example in the rcpptest repository).
这些函数不会导出以供用户直接访问(请参阅rcpptest存储库中的最低可重现性示例)。
I am now attempting to add Stan code to the src/
directory to be compiled when the package is installed (reproducible example in the rcppstan repository). 我现在正在尝试将Stan代码添加到
src/
目录中,以便在安装软件包时进行编译(在rcppstan存储库中可重现的示例)。 However, when I modify the package to work with Stan, I get the following error in R CMD CHECK: 但是,当我修改包以使用Stan时,我在R CMD CHECK中收到以下错误:
#> ❯ checking R code for possible problems ... NOTE
#> meanC: no visible binding for global variable ‘_rcppstan_meanC’
#> Undefined global functions or variables:
#> _rcppstan_meanC
And indeed, when I try to call the R function that uses the meanC
function, I get an error saying Error in meanC(x) : object '_rcppstan_meanC' not found
. 事实上,当我尝试调用使用
meanC
函数的R函数时,我得到一个错误,表示Error in meanC(x) : object '_rcppstan_meanC' not found
出现Error in meanC(x) : object '_rcppstan_meanC' not found
。
From what I can tell, here is what is changing when I modify the package to work with rstan , and thus the likely cause. 从我所知道的,当我修改包以使用rstan时,这是正在改变的,因此可能的原因。
When only using Rcpp , the following is in the src/RcppExports.cpp
: 仅使用Rcpp时 ,以下内容位于
src/RcppExports.cpp
:
static const R_CallMethodDef CallEntries[] = { {"_rcpptest_timesTwo", (DL_FUNC) &_rcpptest_timesTwo, 1}, {NULL, NULL, 0} }; RcppExport void R_init_rcpptest(DllInfo *dll) { R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); R_useDynamicSymbols(dll, FALSE); }
When Stan is incorporated, that code is no longer generated in the src/RcppExports.cpp
file. 当合并Stan时 ,不再在
src/RcppExports.cpp
文件中生成该代码。 Instead, it appears that this is being handles by the src/init.cpp
file created by the rstantools package. 相反,它似乎是由rstantools包创建的
src/init.cpp
文件处理。 The relevant chunk from that file is here: 该文件中的相关块位于:
static const R_CallMethodDef CallEntries[] = { {NULL, NULL, 0} }; void attribute_visible R_init_rcppstan(DllInfo *dll) { // next line is necessary to avoid a NOTE from R CMD check R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); R_useDynamicSymbols(dll, TRUE); // necessary for .onLoad() to work }
Why does the code in src/init.cpp
make the Rcpp functions undefined? 为什么
src/init.cpp
中的代码使Rcpp函数未定义? Conversely, is there a way to edit src/init.cpp
so that the Stan models are able to compile and be accessed correctly, while still allowing the Rcpp functions to be defined? 相反,有没有办法编辑
src/init.cpp
以便Stan模型能够正确编译和访问,同时仍然允许定义Rcpp函数?
The init.cpp
takes of registering methods and Makevars
inhibits compilation of the cpp
files. init.cpp
采用注册方法, Makevars
禁止编译cpp
文件。 With the following changes in Makevars
(and Makevars.win
) I got it to compile: 通过
Makevars
(和Makevars.win
)中的以下更改,我得到了编译:
diff --git a/src/Makevars b/src/Makevars
index 7aedc5b..3ea312e 100644
--- a/src/Makevars
+++ b/src/Makevars
@@ -1,8 +1,9 @@
STANHEADERS_SRC = `"$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" --vanilla -e "cat(system.file('include', 'src', package = 'StanHeaders'))"`
PKG_CPPFLAGS = -I"../inst/include" -I"$(STANHEADERS_SRC)" -DBOOST_RESULT_OF_USE_TR1 -DBOOST_NO_DECLTYPE -DBOOST_DISABLE_ASSERTS -DEIGEN_NO_DEBUG -DBOOST_MATH_OVERFLOW_ERROR_POLICY=errno_on_error
-SOURCES = $(wildcard stan_files/*.stan)
-OBJECTS = $(SOURCES:.stan=.o) init.o
+CPP_SOURCES = $(wildcard *.cpp)
+STAN_SOURCES = $(wildcard stan_files/*.stan)
+OBJECTS = $(STAN_SOURCES:.stan=.o) $(CPP_SOURCES:.cpp=.o)
all: $(SHLIB)
@if test -e "/usr/bin/install_name_tool" && test -e "/usr/local/clang4/lib/libc++.1.dylib" && test -e "/usr/lib/libc++.1.dylib"; then /usr/bin/install_name_tool -change /usr/local/clang4/lib/libc++.1.dylib /usr/lib/libc++.1.dylib $(SHLIB); fi
After calling Rcpp::compileAttributes()
the method registration was again present in RcppExports.cpp
. 在调用
Rcpp::compileAttributes()
,方法注册再次出现在RcppExports.cpp
。 When I tried R CMD INSTALL
, I got an error from .onLoad()
, cf https://github.com/stan-dev/rstanarm/issues/190 . 当我尝试
R CMD INSTALL
,我收到了来自.onLoad()
的错误,cf https://github.com/stan-dev/rstanarm/issues/190 。 Using the workaround from there, ie R CMD INSTALL --preclean
solved the issue first, but was not reliable. 使用那里的解决方法,即
R CMD INSTALL --preclean
解决了问题,但不可靠。 What solved the issue for me was to change 为我解决问题的是改变
R_useDynamicSymbols(dll, FALSE);
into 成
R_useDynamicSymbols(dll, TRUE);
in RcppExports.cpp
. 在
RcppExports.cpp
。 That is of course problematic, since that file might be overwritten, in particular when RStudio/devtools is used. 这当然是有问题的,因为该文件可能被覆盖,特别是在使用RStudio / devtools时。 A rather hacky solution would be to add
一个相当hacky的解决方案是添加
RcppExports.o: patch
patch:
sed -i 's/R_useDynamicSymbols(dll, FALSE)/R_useDynamicSymbols(dll, TRUE)/' RcppExports.cpp
.phony: all clean patch
in the Makevars(.win)
. 在
Makevars(.win)
。 But in the end the problem seems to be that C++ code for Rcpp modules is generated during package installation in a subdirectory of src
. 但最终问题似乎是Rcpp模块的C ++代码是在
src
子目录中的软件包安装过程中生成的。 Therefore Rcpp::compileAttributes()
cannot include the corresponding methofs in the list of registered methods. 因此,
Rcpp::compileAttributes()
不能在已注册方法列表中包含相应的methofs。 I do not see a good solution for that. 我没有看到一个很好的解决方案。 Now the package builds, checks and installs with two NOTEs:
现在,软件包构建,检查并安装两个NOTE:
N checking installed package size
installed size is 7.8Mb
sub-directories of 1Mb or more:
libs 7.7Mb
N checking for GNU extensions in Makefiles
GNU make is a SystemRequirements.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.