Rcpp: невозможно загрузить общий объект, неопределенный символ

Я пытаюсь использовать Rcpp для расширения функциональности от BayesOpt библиотека C++ в R. Я давний пользователь R, но относительно новый для C++, и у меня возникают некоторые проблемы. Я следил за виньетками Rcpp для настройки пакета, который, как я понимаю, является лучшим способом привлечения внешних библиотек c++.

Я установил pkg_cppflags и PKG_LIBS в src/Makevars в BayesOpt, включая папки и библиотеку, и у меня есть один .cpp-файл (назовите его test.СРР) в src/, который использует #include для некоторых файлов заголовков из BayesOpt. В этом файле у меня есть // [[Rcpp::export]] над функцией, которую я хочу экспортировать.

когда я запускаю R CMD check mypackage, библиотека, похоже, работает успешно - глядя на журнал, все идет хорошо, пока она не попытается загрузить пакет, который был только что "установлен". Тогда я получаю

** testing if installed package can be loaded
Error in dyn.load(file, DLLpath = DLLpath, ...) : 
  unable to load shared object '/home/me/p3/mypackage.Rcheck/mypackage/libs/mypackage.so':
   /home/me/p3/mypackage.Rcheck/mypackage/libs/mypackage.so: undefined symbol: _ZTIN8bayesopt13DiscreteModelE

в журнале ошибок. echo _ZTIN8bayesopt13DiscreteModelE | c++filt дает typeinfo for bayesopt::DiscreteModel, который является первым объектом в моем тесте.cpp-файл, который использует заголовки BayesOpt. Я посмотрел высоко и низко для решения этого, но я не могу найти его. Я хотел бы верить, что Makevars указывает на библиотеку правильно, потому что он может найти файлы заголовков во время первой проверки установки-только при загрузке пакета-кандидата я получаю эту неопределенную ошибку символа. Я просмотрел пример Rcpp, который использует внешние библиотеки, но тот, на который указывает Дирк в ответах, которые я просмотрел,RcppGSL, имеет 3500 + line configure скрипт, который заполняет Makevars, и это немного трудно разобрать.

Я был бы признателен за любую помощь - мое последнее средство-сбросить все в src но это кажется громоздким и менее чем элегантным для библиотеки, которая уже аккуратно организована.

1 ответов


не смотри на configure скрипт, который автоматически ... посмотри на configure.ac который является его источником, и который все 5 строк, которые имеют значение (см. ниже) плюс, возможно, 5 строк настройки и отделки.

и в двух словах, вам может просто понадобиться загрузить значения для обоих заголовков (через -I...) и связывание (через -L... -l...).

и для этого мы делаем это в src/Makevars.in:

# set by configure
GSL_CFLAGS = @GSL_CFLAGS@
GSL_LIBS   = @GSL_LIBS@

# combine with standard arguments for R
PKG_CPPFLAGS = $(GSL_CFLAGS) -I../inst/include
PKG_LIBS = $(GSL_LIBS) 

две переменные, обозначаемые @GSL...@ как установить через configure и configure.ac (в сущности) просто звонит gsl-config после утверждения, что у нас есть:

## Use gsl-config to find arguments for compiler and linker flags
##
## Check for non-standard programs: gsl-config(1)
AC_PATH_PROG([GSL_CONFIG], [gsl-config])
## If gsl-config was found, let's use it
if test "${GSL_CONFIG}" != ""; then
    # Use gsl-config for header and linker arguments
    GSL_CFLAGS=`${GSL_CONFIG} --cflags`
    GSL_LIBS=`${GSL_CONFIG} --libs`
else
    AC_MSG_ERROR([gsl-config not found, is GSL installed?])
fi

многие другие библиотеки, созданные за последнее десятилетие или около того, используют аналогичный (но более общий) инструмент под названием pkg-config который служит той же цели: передайте флаги компиляции и компоновщика программам, использующим библиотеку.

и do нужны оба, ваш комментарий

я хотел бы верить, что Makevars указывает на библиотеку правильно, потому что это может найти файлы заголовков во время первой проверки установки

указывает, что у вас есть сборник разобраться, но не связывание или, возможно, не системное обеспечение вашей библиотеки. Опять же, для RcppGSL заключительная строка во время сборки следующая (отредактированная для краткости)

g++ -shared -L/usr/lib/R/lib -o RcppGSL.so \
 RcppExports.o fastLm.o setErrorHandler.o \
 -L/usr/lib/x86_64-linux-gnu -lgsl -lgslcblas \
 -lm -L/usr/lib/R/lib -lR

он связывает три исходных файла с двумя библиотеками, связанными с GSL, а также с R и математической библиотекой. Вы должны увидеть что-то подобное в ваша сборка, или она неправильно настроена.

Edit: и если вы связываете BayesOpt в свой пакет, то вам нужно построить его в static библиотека и список, который в src/Makevars. Это другой случай использования: для RcppGSL мы ищем система установка GSL. Местные разные. Вы можете изучить пакет nloptr, который имеет дело с обоими случаями.