Функции Rcpp не определены при использовании вместе со Stan - PullRequest
0 голосов
/ 04 июня 2018

У меня есть пакет 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

И действительно, когда я пытаюсь вызвать функцию R, которая использует функцию meanC,Я получаю сообщение об ошибке: Error in meanC(x) : object '_rcppstan_meanC' not found.

Из того, что я могу сказать, вот что меняется, когда я изменяю пакет для работы с rstan , и, следовательно, вероятная причина.

  1. При использовании только 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. При Stan включено, этот код больше не генерируется в файле src/RcppExports.cpp.Вместо этого кажется, что это обрабатывается файлом src/init.cpp, созданным пакетом rstantools .Соответствующий фрагмент этого файла находится здесь:

    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 ?

1 Ответ

0 голосов
/ 05 июня 2018

init.cpp принимает методы регистрации, а Makevars запрещает компиляцию файлов cpp.Со следующими изменениями в MakevarsMakevars.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(), ср https://github.com/stan-dev/rstanarm/issues/190. Использование обходного пути, то есть R CMD INSTALL --preclean сначала решило проблему, но не было надежным.Что решило проблему для меня, так это изменить

R_useDynamicSymbols(dll, FALSE);

на

R_useDynamicSymbols(dll, TRUE);

в RcppExports.cpp.Это, конечно, проблематично, поскольку этот файл может быть перезаписан, в частности, когда используется RStudio / devtools.Довольно хакерским решением было бы добавить

RcppExports.o: patch

patch:
        sed -i 's/R_useDynamicSymbols(dll, FALSE)/R_useDynamicSymbols(dll, TRUE)/' RcppExports.cpp

.phony: all clean patch

в Makevars(.win).Но, в конце концов, проблема заключается в том, что код C ++ для модулей Rcpp генерируется во время установки пакета в подкаталоге src.Поэтому Rcpp::compileAttributes() не может включить соответствующие метофы в список зарегистрированных методов.Я не вижу хорошего решения для этого.Теперь пакет собирается, проверяется и устанавливается с двумя примечаниями:

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.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...