Подтвердить что ты не робот

Использование сторонних файлов заголовков с 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>

(Thats from Hadley/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 файлах - это все код на С++, и разница между ними заключается в том, что программист на С++ должен правильно организовывать вещи. Я оставлю обсуждение Разница здесь, но простой поиск здесь на 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 Но до сих пор cut-and-paste работала с минимальной суетой для меня с 6 различными простыми файлами .h)

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

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

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

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

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

B) Теперь создайте свой пакет с помощью Rcpp.package.skeleton() или используйте функциональные возможности Build в RStudio (настоятельно рекомендуется). Вы можете найти информацию об использовании Rcpp.package.skeleton() в hadley/devtools или Атрибуты Rcpp Виньетка. Полная документация для написания пакетов с Rcpp находится в Написание пакета, который использует Rcpp, однако это предполагает, что вы хорошо знаете свой путь вокруг С++, и не использует новый способ "Атрибуты" для выполнения 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, а есть "". Это соглашение на С++ при включении локальных файлов, предоставляемых пользователем, а не в библиотечный файл, такой как Rcpp или STL и т.д.

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

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

4b9b3361

Ответ 1

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

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

  • В пакете R, который вы указываете в атрибуте Rcpp::depends

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

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

Ответ 2

Мне удалось связать любую библиотеку (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++ и ссылку flags. Эта информация обычно может быть получена с помощью pkg-config:

pkg-config --cflags --libs mylib

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

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

Ответ 3

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

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

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

Ответ 4

Пара вещей:

  • "Библиотеки заголовков сторонних разработчиков", как в вашем субъекте, не имеет смысла.

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

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

  • Итак, в этом случае напишите пакет.

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

Ответ 5

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

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

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

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

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

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