简体   繁体   English

当与Stan一起使用时,Rcpp函数未定义

[英]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时,这是正在改变的,因此可能的原因。

  1. 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); } 
  2. 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM