otro incluir hacer crear como cabecera archivos archivo c++ r rcpp

c++ - incluir - crear archivos de cabecera en c



Usar archivos de encabezado de terceros con Rcpp (7)

Tengo un archivo de cabecera llamado coolStuff.h que contiene una función awesomeSauce(arg1) que me gustaría usar en mi archivo fuente cpp.

Estructura de directorios:

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

El código:

#include <Rcpp.h> #include <cppHeaders/coolStuff.h> using namespace Rcpp; // [[Rcpp::export]] double someFunctionCpp(double someInput){ double someOutput = awesomeSauce(someInput); return someOutput; }

Me sale el error:

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

He movido el archivo y el directorio por todo el lugar y parece que esto no funciona. Veo ejemplos sobre el uso de encabezados de terceros que dicen simplemente hacer esto:

#include <boost/array.hpp>

(Eso es de Hadley / devtools)

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

Entonces, ¿qué da? He estado buscando toda la mañana y no puedo encontrar una respuesta a lo que me parece una cosa simple.

ACTUALIZACIÓN 01.11.12

Ok, ahora que he descubierto cómo crear paquetes que usan Rcpp en Rstudio, permítanme reformular la pregunta. Tengo un archivo de encabezado independiente coolStuff.h que contiene una función que quiero usar en mi código cpp.

1) ¿Dónde debería colocar coolStuff.h en la estructura del directorio del paquete para que la función que contiene pueda ser utilizada por el archivo CppFile.cpp?

2) ¿Cómo puedo llamar a coolStuff.h en los archivos cpp? De nuevo, gracias por tu ayuda. Aprendí mucho de la última conversación.

Nota: Leí la viñeta "Escribir un paquete que usa Rcpp" y no explica cómo hacerlo.

La respuesta:

Ok, déjame resumir la respuesta a mi pregunta, ya que está dispersa en esta página. Si recibo un detalle incorrecto, siéntase libre de editar esto o hágamelo saber y lo editaré:

Así que encontró un archivo .h o .cpp que contiene una función u otro código que desea usar en un archivo .cpp que está escribiendo para usar con Rcpp .

coolStuff.h llamando a este código encontrado coolStuff.h y llame a la función que desee utilizar awesomeSauce() . theCppFile.cpp al archivo que está escribiendo theCppFile.cpp .

(Debo señalar aquí que el código en los archivos .h y en los archivos .cpp es todo código C ++ y la diferencia entre ellos es que el programador C ++ mantenga las cosas organizadas de la manera adecuada. Dejaré una discusión de la diferencia aquí , pero una simple búsqueda aquí en SO lo llevará a la discusión de la diferencia. Para usted, el programador de R que necesita usar un bit de código que encontró, no existe una diferencia real).

EN CORTO: Puede usar un archivo como coolStuff.h siempre que no llame a otras bibliotecas, cortando y pegando en el theCppFile.cpp , o si crea un paquete, puede colocar el archivo en el directorio /src con theCppFile.cpp y usa #include "coolStuff.h" en la parte superior del archivo que estás escribiendo. Este último es más flexible y le permite usar funciones en coolStuff.h en otros archivos .cpp .

DETALLES:

1) coolStuff.h no debe llamar a otras bibliotecas. Entonces eso significa que no puede tener ninguna declaración de inclusión en la parte superior. Si lo hace, lo que detallo a continuación probablemente no funcionará, y el uso del código encontrado que llama a otras bibliotecas está fuera del alcance de esta respuesta.

2) Si quiere compilar el archivo con sourceCpp() , necesita cortar y pegar coolStuff.h en el theCppFile.cpp . Me dijeron que hay excepciones, pero sourceCpp() está diseñado para compilar un archivo .cpp , por lo que es la mejor ruta para tomar.

(NOTA: No garantizo que un simple corte y pegado funcionará de la caja. Es posible que tenga que cambiar el nombre de las variables o, más probablemente, cambiar los tipos de datos utilizados para que sean consistentes con los que está utilizando en el theCppFile.cpp . hasta ahora, cortar y pegar ha funcionado con un mínimo de alboroto para mí con 6 archivos .h simples diferentes)

3) Si solo necesita usar código de coolStuff.h en el theCppFile.cpp y en ningún otro lugar, debe cortarlo y pegarlo en el theCppFile.cpp .

(De nuevo, no garantizo que vea la nota anterior sobre cortar y pegar)

4) Si desea utilizar el código contenido en coolStuff.h en el theCppFile.cpp Y otros archivos .cpp , debe considerar la creación de un paquete. Esto no es difícil, pero puede ser un poco complicado, porque la información sobre la construcción de paquetes con Rcpp va desde la exhaustiva documentación exhaustiva que desea con cualquier paquete R (pero que está por encima de su cabeza como novato), y el novato sensible introducciones (que pueden omitir un detalle que necesita).

Esto es lo que sugiero:

A) Primero obtenga una versión de theCppFile.cpp con el código de coolStuff.h cortar y pegar en el theCppFile.cpp que compila con sourceCpp() y funciona como espera. Esto no es obligatorio, pero si es nuevo en los paquetes Rcpp OR, es bueno asegurarse de que su código funcione en esta situación simple antes de pasar al caso más complicado a continuación.

B) Ahora crea tu paquete usando Rcpp.package.skeleton() o usa la funcionalidad Build en RStudio (ALTAMENTE recomendado). Puede encontrar detalles sobre el uso de Rcpp.package.skeleton() en https://github.com/hadley/devtools/wiki/Rcpp o Rtpp Attributes Vignette . La documentación completa para escribir paquetes con Rcpp está en Escribir un paquete que usa Rcpp , sin embargo, esto supone que conoce bastante bien C ++ y no usa la nueva forma de "Atributos" para hacer Rcpp.

No olvides "Build & Reload" si utilizas RStudio o compileAttributes() si no estás en RStudio.

C) Ahora debería ver en su directorio / R un archivo llamado RcppExports.R . Ábrelo y compruébalo. En RcppExports.R debería ver las funciones del derivador R para todos los archivos .cpp que tiene en su directorio /src . Muy dulce.

D) Pruebe la función R que corresponde a la función que escribió en el theCppFile.cpp . ¿Funciona? Si es así, sigue adelante.

E) Con su paquete creado, puede mover coolStuff.h a la carpeta src con el archivo theCppFile.cpp .

F) Ahora puede eliminar el código de cortar y pegar de theCppFile.cpp y en la parte superior de theCppFile.cpp (y de cualquier otro archivo .cpp que desee usar el código de coolStuff.h) ponga #include "coolStuff.h" justo después de #include <Rcpp.h> . Tenga en cuenta que no hay corchetes en torno a ranker.h, sino que hay "". Esta es una convención de C ++ cuando se incluyen los archivos locales proporcionados por el usuario en lugar de un archivo de biblioteca como Rcpp o STL, etc ...

G) Ahora tienes que reconstruir el paquete. En RStudio esto es solo "Build & Reload" en el menú Build. Si no está utilizando RStudio, debe ejecutar compileAttributes()

H) Ahora intenta la función R nuevamente tal como lo hiciste en el paso D), con suerte funciona.


El problema es que sourceCpp está expresamente diseñado para compilar solo un único archivo fuente independiente. Si desea que sourceCpp tenga dependencias, entonces deben ser:

  1. En el sistema, incluya directorios (es decir, /usr/local/lib o /usr/lib ); o

  2. En un paquete R que enumera en un atributo Rcpp::depends

Como dijo Dirk, si desea construir más de un archivo fuente, entonces debería considerar usar un paquete R en lugar de sourceCpp .

Tenga en cuenta que si está trabajando en un paquete y ejecuta sourceCpp en un archivo dentro del directorio src del paquete, lo compilará como si estuviera en el paquete (es decir, puede incluir archivos del directorio src o del directorio inst / include).


Esto funcionó para mí en Windows:

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

Editar: En realidad, no es necesario si usa Boost Headers (gracias a Ralf Stubner):

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


Los corchetes angulares <> son para el sistema incluye, como las libs estándar.

Para los archivos locales de su propio proyecto, use comillas: "".

Además, si coloca los encabezados en un directorio diferente, la ruta del encabezado debe especificarse localmente en el archivo fuente que lo incluye.

Entonces, para su ejemplo, esto debería funcionar:

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

Puede configurar las rutas de búsqueda para que el archivo se pueda encontrar sin hacer eso, pero generalmente solo vale la pena hacer eso para las cosas que desea incluir en varios proyectos, o de lo contrario esperaría que alguien lo "instale".


Podemos agregarlo escribiendo la ruta al encabezado en la variable .R/Makevars archivo .R/Makevars como se muestra a continuación. El siguiente es un ejemplo de xtensor agregar un archivo de encabezado de xtensor instalado con Anaconda en 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


Pude vincular cualquier biblioteca (MPFR en este caso) estableciendo dos variables de entorno antes de llamar a sourceCpp:

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

La primera variable contiene la ruta de los encabezados de la biblioteca. El segundo incluye la ruta del binario de la biblioteca y su nombre de archivo. En este caso, también se requieren otras bibliotecas dependientes. Para más detalles, compruebe la compilación g ++ y los flags enlace. Esta información generalmente se puede obtener usando pkg-config:

pkg-config --cflags --libs mylib

Para una mejor comprensión, recomiendo usar sourceCpp con salida detallada para imprimir la compilación g ++ y los comandos de enlace:

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


Pude vincular una biblioteca de impulso usando el siguiente comando global en R antes de llamar a sourceCpp

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

Básicamente reflejando esta publicación pero con una opción de compilador diferente: http://gallery.rcpp.org/articles/first-steps-with-C++11/


Un par de cosas:

  1. "Bibliotecas de encabezado de terceros" como en su tema no tiene sentido.

  2. Los encabezados de terceros pueden funcionar mediante un código de plantilla donde los encabezados son todo lo que necesita, es decir, solo hay un paso de inclusión y el compilador resuelve las cosas.

  3. Una vez que necesita las bibliotecas y la vinculación real del código objeto, es posible que no pueda acceder al poderoso y útil sourceCpp menos que le haya dado metainformación a través de plugins (o env. Vars).

  4. Entonces, en ese caso, escribe un paquete.

Cosas sencillas y simples son simplemente eso con Rcpp y los nuevos atributos, o la función inline y cxxfunction más cxxfunction . Más para uso complejo --- y las bibliotecas externas son más complejas, necesita consultar la documentación. Agregamos varias viñetas a Rcpp para eso.