Использование сторонних заголовочных файлов с Rcpp

У меня есть файл заголовка coolStuff.h которая содержит функцию awesomeSauce(arg1) что я хотел бы использовать в моем исходном файле cpp.

Структура каталогов:

  • RworkingDirectory
    • sourceCpp
      • theCppFile.cpp
    • cppHeaders
      • coolStuff.h

Код:

#include <Rcpp.h>
#include <cppHeaders/coolStuff.h>
using namespace Rcpp;

// [[Rcpp::export]]
double someFunctionCpp(double someInput){

double someOutput = awesomeSauce(someInput);

return someOutput;
}

Я получаю ошибку:

 theCppFile.cpp:2:31: error: cppHeaders/coolStuff.h: No such file or directory

Я переместил файл и каталог повсюду и не могу заставить его работать. Я вижу примеры повсеместного использования сторонних заголовков, которые говорят просто сделать это:

#include <boost/array.hpp>

(Это от Хэдли / devtools)

https://github.com/hadley/devtools/wiki/Rcpp

Так что же дает? Я искал все утро и не могу найти ответ на то, что мне кажется простым делом.

ОБНОВЛЕНИЕ 01.11.12

Хорошо, теперь, когда я понял, как создавать пакеты, которые используют Rcpp в Rstudio, позвольте мне перефразировать вопрос. У меня есть отдельный заголовочный файл coolStuff.h, который содержит функцию, которую я хочу использовать в своем коде cpp.

1) Где я должен поместить файл coolStuff.h в структуру каталогов пакета, чтобы содержащаяся в нем функция могла использоваться в CppFile.cpp?

2) Как мне вызвать coolStuff.h в файлах cpp? В очередной раз благодарим за помощь. Я многому научился из последнего разговора.

Примечание: я прочитал виньетку «Написание пакета, использующего Rcpp», и он не объясняет, как это сделать.

Ответ:

Хорошо, позвольте мне обобщить ответ на мой вопрос, так как он разбросан по всей этой странице. Если я ошибаюсь в деталях, не стесняйтесь редактировать это или дайте мне знать, и я отредактирую это:

Итак, вы нашли .h или же .cpp файл, который содержит функцию или какой-то другой бит кода, который вы хотите использовать в .cpp файл, который вы пишете для использования Rcpp,

Давайте продолжать называть этот найденный код coolStuff.h и вызвать функцию, которую вы хотите использовать awesomeSauce(), Позволяет вызвать файл, который вы пишете theCppFile.cpp,

(Здесь я должен отметить, что код в файлах .h и в файлах .cpp — это весь код C ++, и разница между ними заключается в том, чтобы программист C ++ организовывал вещи должным образом. Я оставлю обсуждение различий здесь , но простой поиск здесь на SO приведет вас к обсуждению разницы. Для вас, программиста R, которому нужно использовать немного кода, который вы нашли, нет никакой реальной разницы.)

КОРОЧЕ: Вы можете использовать файл как coolStuff.h при условии, что он не вызывает никаких других библиотек, либо вырезать и вставить в theCppFile.cppили, если вы создаете пакет, вы можете поместить файл в \src каталог с theCppFile.cpp файл и использование #include "coolStuff.h" в верхней части файла, который вы пишете. Последний является более гибким и позволяет использовать функции в coolStuff.h в других .cpp файлы.

ПОДРОБНОСТИ:

1) coolStuff.h не должны вызывать другие библиотеки. Таким образом, это означает, что в верхней части не может быть никаких операторов включения. Если это произойдет, то, что я подробно опишу ниже, вероятно, не будет работать, и использование найденного кода, который вызывает другие библиотеки, выходит за рамки этого ответа.

2) Если вы хотите скомпилировать файл с sourceCpp() вам нужно вырезать и вставлять coolStuff.h в theCppFile.cpp, Мне говорят, что есть исключения, но sourceCpp() предназначен для компиляции одного .cpp файл, так что это лучший путь.

(ПРИМЕЧАНИЕ. Я не даю никаких гарантий, что простое вырезание и вставка будут работать из коробки. Возможно, вам придется переименовать переменные или, скорее, переключить используемые типы данных, чтобы они соответствовали тем, которые вы используете в theCppFile.cpp, Но до сих пор, вырезать и вставить работал с минимальной суетой для меня с 6 различными простыми .h файлы)

3) Если вам нужно только использовать код из coolStuff.h в theCppFile.cpp и больше нигде, тогда вы должны вырезать и вставить его в theCppFile.cpp,

(Опять же, я не даю никаких гарантий, см. Примечание выше о вырезке и вставке)

4) Если вы хотите использовать код, содержащийся в coolStuff.h в theCppFile.cpp И другие .cpp файлы, вы должны посмотреть на создание пакета. Это не сложно, но может быть немного сложно, потому что информация о сборке пакетов с помощью Rcpp варьируется от исчерпывающей исчерпывающей документации, которую вы хотите получить с любым пакетом R (но это выше вашего понимания как новичок), и новичка, чувствительного к этому. введения (которые могут опустить детали вы случиться нужно).

Вот что я предлагаю:

А) Сначала получите версию theCppFile.cpp с кодом из coolStuff.h вырезать и вставлять в theCppFile.cpp который компилируется с sourceCpp() и работает так, как вы ожидаете. Это не обязательно, но если вы новичок в пакетах Rcpp OR, неплохо убедиться, что ваш код работает в этой простой ситуации, прежде чем переходить к более сложному случаю ниже.

B) Теперь создайте свой пакет, используя Rcpp.package.skeleton() или используйте функциональность Build в RStudio (НАСТОЯТЕЛЬНО рекомендуется). Вы можете найти подробную информацию об использовании Rcpp.package.skeleton() в Hadley / DevTools или же Rcpp атрибуты виньетка. Полная документация для написания пакетов с Rcpp находится в Написание пакета, который использует Rcpp, однако этот предполагает, что вы достаточно хорошо разбираетесь в C ++, и не использует новый способ «Атрибутов» для выполнения Rcpp.

Не забудьте «построить» & Обновить «, если используется RStudio или compileAttributes() если вы не в RStudio.

C) Теперь вы должны увидеть в вашем каталоге \ R файл с именем RcppExports.R, Откройте это и проверьте это. В RcppExports.R Вы должны увидеть функции оболочки R для всех файлов .cpp, которые есть в вашем \src каталог. Довольно мило.

D) Попробуйте функцию R, которая соответствует функции, которую вы написали в theCppFile.cpp, Это работает? Если так, то иди дальше.

E) С вашим пакетом вы можете двигаться coolStuff.h в src папка с theCppFile.cpp,

F) Теперь вы можете удалить код вырезания и вставки из theCppFile.cpp и на вершине theCppFile.cpp (и любой другой файл .cpp, в котором вы хотите использовать код из coolStuff.h) #include "coolStuff.h" сразу после #include <Rcpp.h>, Обратите внимание, что вокруг ranker.h нет скобок, скорее есть «». Это соглашение C ++ при включении локальных файлов, предоставляемых пользователем, а не файла библиотеки, такого как Rcpp или STL и т. Д.

G) Теперь вам нужно пересобрать пакет. В RStudio это просто «Build & Перезагрузить »в меню Build. Если вы не используете RStudio, вы должны запустить compileAttributes()

H) Теперь попробуйте снова функцию R, как вы делали на шаге D), надеюсь, она сработает.

32

Решение

Проблема в том, что sourceCpp специально разработан для создания только одного автономного исходного файла. Если ты хочешь sourceCpp чтобы иметь зависимости, то они должны быть:

  1. В систему входят каталоги (т.е. /usr/local/lib или же /usr/lib); или же

  2. В пакете R, который вы перечисляете в Rcpp::depends атрибут

Как сказал Дирк, если вы хотите собрать более одного исходного файла, вам следует рассмотреть возможность использования пакета R, а не sourceCpp,

Обратите внимание, что если вы работаете с пакетом и выполняете sourceCpp для файла в каталоге src пакета, он соберет его как будто он находится в пакете (то есть вы можете включать файлы из каталога src или каталога inst / include).

20

Другие решения

Мне удалось связать любую библиотеку (в данном случае MPFR), установив две переменные среды перед вызовом sourceCpp:

Sys.setenv("PKG_CXXFLAGS"="-I/usr/include")
Sys.setenv("PKG_LIBS"="-L/usr/lib/x86_64-linux-gnu/ -lm -lmpc -lgmp -lmpfr")

Первая переменная содержит путь к заголовкам библиотеки. Второй включает в себя путь к двоичному файлу библиотеки и имя файла. В этом случае также требуются другие зависимые библиотеки. Для более подробной информации проверьте компиляцию g ++ и ссылку флаги. Эту информацию обычно можно получить с помощью pkg-config:

pkg-config --cflags --libs mylib

Для лучшего понимания я рекомендую использовать sourceCpp с подробным выводом для печати команд компиляции и связывания g ++:

sourceCpp("mysource.cpp", verbose=TRUE, rebuild=TRUE)
5

Я смог связать библиотеку наддува с помощью следующей глобальной команды в R перед вызовом sourceCpp

Sys.setenv("PKG_CXXFLAGS"="-I \path-to-boost\")

В основном зеркальное отражение этого поста, но с другой опцией компилятора: http://gallery.rcpp.org/articles/first-steps-with-C++11/

4

Пара вещей:

  1. «Сторонние библиотеки заголовков» как в вашей теме не имеют смысла.

  2. Сторонние заголовки могут работать через шаблонный код, где заголовки — это все, что вам нужно, то есть есть только шаг включения, и компилятор решает проблемы.

  3. Если вам нужны библиотеки и фактическое связывание объектного кода, вы не сможете получить мощную и полезную sourceCpp если вы не предоставили ему мета-информацию через плагины (или env. vars).

  4. Так что в этом случае напишите пакет.

Легкие и простые вещи — это то же самое, что с Rcpp и новыми атрибутами, или старыми встроенными и cxxfunction, Больше для комплексного использования — и внешние библиотеки является Более сложный, вам нужно ознакомиться с документацией. Для этого мы добавили несколько виньеток в Rcpp.

2

Угловые скобки <> Для системных включений, таких как стандартные библиотеки.

Для файлов, локальных для вашего собственного проекта, используйте кавычки: «».

Кроме того, если вы размещаете заголовки в другом каталоге, путь к заголовку должен быть указан локально по отношению к исходному файлу, включая его.

Так что для вашего примера это должно работать:

#include "../cppHeaders/coolStuff.h"

Вы можете настроить пути поиска таким образом, чтобы файл мог быть найден без этого, но, как правило, это стоит делать только для тех вещей, которые вы хотите включить в несколько проектов, или иначе ожидаете, что кто-то «установит».

1

Мы можем добавить его, написав путь к заголовку в PKG_CXXFLAGS переменная .R/Makevars файл, как показано ниже. Ниже приведен пример добавления файла заголовка xtensor установлен с Anaconda в macOS.

⋊> ~ cat ~/.R/Makevars
CC=/usr/local/bin/gcc-7
CXX=/usr/local/bin/g++-7
CPLUS_INCLUDE_PATH=/opt/local/include:$CPLUS_INCLUDE_PATH
PKG_CXXFLAGS=-I/Users/kuroyanagi/.pyenv/versions/miniconda3-4.3.30/include
LD_LIBRARY_PATH=/opt/local/lib:$LD_LIBRARY_PATH
CXXFLAGS= -g0 -O3 -Wall
MAKE=make -j4
1

Это работало для меня в Windows:

Sys.setenv("PKG_CXXFLAGS"='-I"C:/boost/boost_1_66_0"')

Изменить: На самом деле вам это не нужно, если вы используете Boost Headers (спасибо Ральфу Стубнеру):

// [[Rcpp::depends(BH)]]

0
По вопросам рекламы [email protected]