ошибка useDynLib() и compileAttributes ничего не возвращает: встраивание библиотеки C в пакет R

У меня есть пакет C, который создает исполняемый файл с несколькими флагами аргументов. Один компилирует код с помощью Makefile (я знаю, это нужно изменить для пакета R), и создается исполняемый файл для запуска через

$ ./codeName -f path/inputfile -o path/outputfile -p ## -s "type"

Моя цель — интегрировать несколько функций, используемых в этом пакете C, для использования с библиотекой R. Я взгляну на несколько примеров github.com/cran пакетов R, использующих C. В статье «Написание расширений R» объясняется, как я могу использовать .Call() и Makevars для вызова функций C из R. Я хотел бы избежать этого, как чумы. Однако похоже, что это потребует значительного переписывания объекта SEXP, поэтому я обращаюсь к Rcpp (ага!)

Я создаю пакет Rcpp.package.skeleton("packageName")

Большой. В R я делаю следующее:

$ R
> library(devtools)
> build()  # works!
> install() # works!
> library(packageName)
> rcpp_hello_world()
## expected output

Все работает. Затем я добавляю свой пакет C в /src. Затем я выполняю Rcpp::compileAttributes() в корневом каталоге пакета через R - ничего не происходит и ничего не выводится, чего и следовало ожидать, так как я еще не изменил код C.

Я пытаюсь установить с помощью команд выше: devtools::build() и devtools::install(). Судя по Makefile, код C компилируется отлично! Но тут такая проблема:

** R
** preparing package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded
Error in library.dynam(lib, package, package.lib) : 
  shared object ‘packageName.so’ not found
Error: loading failed
Execution halted'
ERROR: loading failed

Что ж, это несколько сбивает с толку, и я не знаю, почему это произошло, но загвоздка в том, что useDynLib("packageName") в ПРОСТРАНСТВЕ ИМЕН. Если я удалю это, код C будет скомпилирован, и пакет будет установлен с помощью команд build/install выше. rcpp_hello_world() все еще работает.

(1) Почему сейчас появляется эта ошибка ‘packageName.so’ not found и можно ли ее обойти?

(Этот вопрос не имеет ничего общего с Rcpp.)

Затем я перехожу к файлу .c. я добавить

#include <Rcpp.h>
using namespace Rcpp;

в файл *.c и //[[Rcpp::export]] перед функцией, которую я хотел бы импортировать. (Я не уверен, что это будет работать в *.c или в заголовочном файле C.)

Затем я иду в корневой каталог пакета, открываю R и пробую следующее:

$ R
> library(Rcpp)
> compileAttributes()

Это работает без ошибок. Однако RcppExports.R и RcppExports.cpp не были сгенерированы. Компиляция кода C также приводит к ошибке, что он не может найти #include <Rcpp.h>.

(2) Почему compileAttributes() не работает в этой среде? Должно быть, я неправильно использую Rcpp и //[[Rcpp::export]], чтобы обернуть эти функции C в формат, пригодный для использования в R.


person ShanZhengYang    schedule 27.11.2017    source источник
comment
Вы можете начать с другой стороны с рабочего пакета, созданного Rcpp.package.skeleton() или эквивалентной функцией в RStudio, а затем сравнить. Здесь должно быть что-то другое.   -  person Dirk Eddelbuettel    schedule 27.11.2017
comment
Кроме того, очень очевидный: Rcpp и compileAttributes() ожидают код C++. Не C-код. Таким образом, файлы, оканчивающиеся на .c, игнорируются преднамеренно. Просто переименуйте файлы...   -  person Dirk Eddelbuettel    schedule 27.11.2017
comment
@DirkEddelbuettel Спасибо за вклад. Изменение расширения на .cpp приводит к некоторым ошибкам компиляции... Чтобы сохранить код C без изменений, мне, возможно, придется прибегнуть к написанию SEXP...   -  person ShanZhengYang    schedule 27.11.2017
comment
Либо вы хотите C++ и Rcpp и можете получить конвертеры, написанные для вас (т.е. нет, вам не нужно использовать SEXP) или вы хотите простой C, и в этом случае ваш квест для compileAttributes() неправильно.   -  person Dirk Eddelbuettel    schedule 27.11.2017
comment
@DirkEddelbuettel В этом случае, если я не смогу передать код C через cFunction(), нет никакого способа упростить интеграцию ванильного кода C с помощью Rcpp (если только я не смогу перевести код C на C++)?   -  person ShanZhengYang    schedule 28.11.2017


Ответы (1)


Как бы вы назвали эту функцию? С-код?

int fib(int n) { 
   if (n < 2) return n;
   return fib(n-1) + fib(n-2);
}

Он проходит как код C и C++. Итак, давайте назовем это C-кодом.

Вы можете явно связать это с R через Rcpp со следующим вызывающим абонентом:

// [[Rcpp::export]]
int callFib(int n) {
   return fib(n);
}

Соедините их все вместе в файл C++, чтобы Rcpp мог работать с ними (см. комментарии), и все готово.

R> library(Rcpp)
R> sourceCpp("/tmp/ex.cpp")

R> callFib(10)
[1] 55
R> 

Полный файл ниже.

#include <Rcpp.h>

int fib(int n) { 
  if (n < 2) return n;
  return fib(n-1) + fib(n-2);
}


// [[Rcpp::export]]
int callFib(int n) {
  return fib(n);
}

/*** R
callFib(10)
*/
person Dirk Eddelbuettel    schedule 27.11.2017
comment
Теперь я понимаю ваши комментарии выше. Спасибо - person ShanZhengYang; 28.11.2017
comment
Таким образом, те же оболочки кода, созданные compileAttributes() с кодом C++, не могут существовать, когда я переименовал файлы в код *.C? Понятия не имею, чем я занимаюсь - person ShanZhengYang; 29.11.2017