Issue
I'm banging my head against the wall trying to get Rcpp
to build a package for SPI on a Raspberry Pi.
My code/package is found at my GitHub: href="https://github.com/mnr/rpigpior/" rel="nofollow noreferrer">https://github.com/mnr/rpigpior/
When I run Rcpp::compileAttributes()
followed by load_all()
I consistently get
RcppExports.cpp:14:32: error: 'spi_config_t' has not been declared
So obviously I haven't declared or linked something important - but I'm unclear on where I need to declare the link and what I need to link.
Has anyone had experience with this sort of thing?
Starting with the package source as found at https://github.com/mnr/rpigpior/
> Rcpp::compileAttributes()
> load_all()
ℹ Loading rpigpior
Exports from /home/pi/Documents/rpigpior/src/rpi_spi_open.cpp:
int rpi_spi_open(char *device, spi_config_t config)
/home/pi/Documents/rpigpior/src/RcppExports.cpp updated.
/home/pi/Documents/rpigpior/R/RcppExports.R updated.
ℹ Re-compiling rpigpior (debug build)
── R CMD INSTALL ───────────────────────────────────────────────────────────────────────────────────────────────────
─ installing *source* package ‘rpigpior’ ... (730ms)
** using staged installation
** libs
using C compiler: ‘gcc (Raspbian 10.2.1-6+rpi1) 10.2.1 20210110’
using C++ compiler: ‘g++ (Raspbian 10.2.1-6+rpi1) 10.2.1 20210110’
g++ -std=gnu++17 -I"/opt/R/release/lib/R/include" -DNDEBUG -I'/home/pi/R/armv7l-unknown-linux-gnueabihf-library/4.3/Rcpp/include' -I/usr/local/include -fPIC -g -O2 -UNDEBUG -Wall -pedantic -g -O0 -fdiagnostics-color=always -c RcppExports.cpp -o RcppExports.o
RcppExports.cpp:14:32: error: ‘spi_config_t’ has not been declared
14 | int rpi_spi_open(char *device, spi_config_t config);
| ^~~~~~~~~~~~
RcppExports.cpp: In function ‘SEXPREC* _rpigpior_rpi_spi_open(SEXPREC**, SEXP)’:
RcppExports.cpp:19:57: error: cannot convert ‘SEXP’ {aka ‘SEXPREC*’} to ‘Rcpp::traits::input_parameter<char>::type*’ {aka ‘Rcpp::InputParameter<char>*’} in initialization
19 | Rcpp::traits::input_parameter< char >::type *device(*deviceSEXP);
| ^~~~~~~~~~~
| |
| SEXP {aka SEXPREC*}
In file included from /home/pi/R/armv7l-unknown-linux-gnueabihf-library/4.3/Rcpp/include/Rcpp/r/headers.h:67,
from /home/pi/R/armv7l-unknown-linux-gnueabihf-library/4.3/Rcpp/include/RcppCommon.h:30,
from /home/pi/R/armv7l-unknown-linux-gnueabihf-library/4.3/Rcpp/include/Rcpp.h:27,
from RcppExports.cpp:4:
/opt/R/release/lib/R/include/Rinternals.h:180:16: note: class type ‘SEXPREC’ is incomplete
180 | typedef struct SEXPREC *SEXP;
| ^~~~~~~
RcppExports.cpp:20:36: error: ‘spi_config_t’ was not declared in this scope
20 | Rcpp::traits::input_parameter< spi_config_t >::type config(configSEXP);
| ^~~~~~~~~~~~
RcppExports.cpp:20:49: error: template argument 1 is invalid
20 | Rcpp::traits::input_parameter< spi_config_t >::type config(configSEXP);
| ^
RcppExports.cpp:20:57: error: expected initializer before ‘config’
20 | Rcpp::traits::input_parameter< spi_config_t >::type config(configSEXP);
| ^~~~~~
RcppExports.cpp:21:56: error: ‘config’ was not declared in this scope
21 | rcpp_result_gen = Rcpp::wrap(rpi_spi_open(*device, config));
| ^~~~~~
make: *** [/opt/R/release/lib/R/etc/Makeconf:200: RcppExports.o] Error 1
ERROR: compilation failed for package ‘rpigpior’
─ removing ‘/tmp/RtmpN8Haun/devtools_install_10981336a33c/rpigpior’
Error in `(function (command = NULL, args = character(), error_on_status = TRUE, …`:
! System command 'R' failed
---
Exit status: 1
stdout & stderr: <printed>
---
Solution
@coatless already identified one key issue: Rcpp
does not know spi_config_t
so you cannot place it in an interface without doing other work. As it is a structure, you need to do more work.
I cloned your repo and after making these changes got it to build
Reduce / change the interface to
int rpi_spi_open(std::string dev)
as we also preferstd::string
tochar *
.Assign the string's value to a
const char*
:const char *device = dev.c_str();
Declare a
spi_config_t
. This is functionally nonsense but we first want to get compilation out of the way.Correct the false comment character
#
to//
Re-build the static library, you included one in your git repo (bad idea) that was wrong for my x86_64 anyway. Copy it in under its name.
Correct
src/Makevars
to usePKG_LIBS = -L. -lspidev-lib++
I think that was it. I can then build a package which includes the compilation step:
$ build.r # convenience wrapper for R CMD build
* checking for file ‘./DESCRIPTION’ ... OK
* preparing ‘rpigpior’:
* checking DESCRIPTION meta-information ... OK
* cleaning src
* installing the package to build vignettes
* creating vignettes ... OK
* cleaning src
* checking for LF line-endings in source and make files and shell scripts
* checking for empty or unneeded directories
* re-saving image files
* building ‘rpigpior_0.1.0.tar.gz’
$
So we reduced your apparent Rcpp down to a logic issue where you now need to figure how to fill the config data structure from R. A different problem, and mostly yours :)
PS I sent you my changes as a pull request at your repo.
Answered By - Dirk Eddelbuettel Answer Checked By - David Goodson (WPSolving Volunteer)