[英]Rcpp functions undefined when used alongside Stan
我有一个R包,它使用Rcpp来实现一些内部功能。 这些函数不会导出以供用户直接访问(请参阅rcpptest存储库中的最低可重现性示例)。
我现在正在尝试将Stan代码添加到src/
目录中,以便在安装软件包时进行编译(在rcppstan存储库中可重现的示例)。 但是,当我修改包以使用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
事实上,当我尝试调用使用meanC
函数的R函数时,我得到一个错误,表示Error in meanC(x) : object '_rcppstan_meanC' not found
出现Error in meanC(x) : object '_rcppstan_meanC' not found
。
从我所知道的,当我修改包以使用rstan时,这是正在改变的,因此可能的原因。
仅使用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); }
当合并Stan时 ,不再在src/RcppExports.cpp
文件中生成该代码。 相反,它似乎是由rstantools包创建的src/init.cpp
文件处理。 该文件中的相关块位于:
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 }
为什么src/init.cpp
中的代码使Rcpp函数未定义? 相反,有没有办法编辑src/init.cpp
以便Stan模型能够正确编译和访问,同时仍然允许定义Rcpp函数?
init.cpp
采用注册方法, Makevars
禁止编译cpp
文件。 通过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
在调用Rcpp::compileAttributes()
,方法注册再次出现在RcppExports.cpp
。 当我尝试R CMD INSTALL
,我收到了来自.onLoad()
的错误,cf https://github.com/stan-dev/rstanarm/issues/190 。 使用那里的解决方法,即R CMD INSTALL --preclean
解决了问题,但不可靠。 为我解决问题的是改变
R_useDynamicSymbols(dll, FALSE);
成
R_useDynamicSymbols(dll, TRUE);
在RcppExports.cpp
。 这当然是有问题的,因为该文件可能被覆盖,特别是在使用RStudio / devtools时。 一个相当hacky的解决方案是添加
RcppExports.o: patch
patch:
sed -i 's/R_useDynamicSymbols(dll, FALSE)/R_useDynamicSymbols(dll, TRUE)/' RcppExports.cpp
.phony: all clean patch
在Makevars(.win)
。 但最终问题似乎是Rcpp模块的C ++代码是在src
子目录中的软件包安装过程中生成的。 因此, Rcpp::compileAttributes()
不能在已注册方法列表中包含相应的methofs。 我没有看到一个很好的解决方案。 现在,软件包构建,检查并安装两个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.