update: Solved in Re: Can't find 'boot_...' symbol when trying to use an installed XS module. /update
I'm working on my next Raspberry Pi project, and am having an issue using the XS module. I generated the XS using Inline::C, copied the file into the distribution directory, and compiled it successfully. However, I'm getting:
Can't find 'boot_RPi__ADC__MCP3008' symbol in /usr/local/lib/perl/5.18
+.2/auto/RPi/ADC/MCP3008/MCP3008.so
at /usr/local/lib/perl/5.18.2/RPi/ADC/MCP3008.pm line 12.
I've gone through an hour's worth of search results, but none explain how I should fix this so I'm at a bit of a loss. All I know is that the error is being generated by XSLoader.
Can the XS Monks have a look to see what I may be missing? I'll happily provide more information/code/files if necessary.
My XS code:
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <wiringPi.h>
#include <wiringPiSPI.h>
static int fd;
void load_spi_driver (){
if (system("gpio load spi") == -1){
fprintf (stderr, "Can't load the SPI driver: %s\n", strerror (
+errno)) ;
exit (EXIT_FAILURE) ;
}
}
void spi_setup (int spi_channel){
if ((fd = wiringPiSPISetup(spi_channel, 1000000)) < 0){
fprintf (stderr, "Can't open the SPI bus: %s\n", strerror (err
+no)) ;
exit (EXIT_FAILURE) ;
}
}
int fetch (int load_spi, int spi, int mode, int input){
if(load_spi == TRUE){
loadSpiDriver();
}
wiringPiSetup () ;
spiSetup(spi);
if(mode == 1){
// single-ended requires 0x08
mode = mode << 3;
}
if(input < 0 || input > 7){
return -1;
}
// start bit
unsigned char buffer[3] = {1};
buffer[1] = (mode + input) << 4;
wiringPiSPIDataRW(spi, buffer, 3);
// get the last 10 bits
return ((buffer[1] & 3) << 8) + buffer[2];
}
MODULE = MCP3008 PACKAGE = MCP3008
PROTOTYPES: DISABLE
void
load_spi_driver ()
PREINIT:
I32* temp;
PPCODE:
temp = PL_markstack_ptr++;
load_spi_driver();
if (PL_markstack_ptr != temp) {
/* truly void, because dXSARGS not invoked */
PL_markstack_ptr = temp;
XSRETURN_EMPTY; /* return empty stack */
}
/* must have used dXSARGS; list context implied */
return; /* assume stack size is correct */
void
spi_setup (spi_channel)
int spi_channel
PREINIT:
I32* temp;
PPCODE:
temp = PL_markstack_ptr++;
spi_setup(spi_channel);
if (PL_markstack_ptr != temp) {
/* truly void, because dXSARGS not invoked */
PL_markstack_ptr = temp;
XSRETURN_EMPTY; /* return empty stack */
}
/* must have used dXSARGS; list context implied */
return; /* assume stack size is correct */
int
fetch (load_spi, spi, mode, input)
int load_spi
int spi
int mode
int input
The relevant piece in the module:
require XSLoader;
XSLoader::load('RPi::ADC::MCP3008', $VERSION);
...and just in case, my makefile:
use strict;
use warnings FATAL => 'all';
use ExtUtils::MakeMaker;
WriteMakefile(
NAME => 'RPi::ADC::MCP3008',
AUTHOR => q{Steve Bertrand <steveb@cpan.org>},
VERSION_FROM => 'lib/RPi/ADC/MCP3008.pm',
ABSTRACT_FROM => 'lib/RPi/ADC/MCP3008.pm',
LICENSE => 'Perl_5',
PL_FILES => {},
LIBS => ['-lwiringPi', '-lpthread'],
MIN_PERL_VERSION => 5.006,
CONFIGURE_REQUIRES => {
'ExtUtils::MakeMaker' => 0,
},
BUILD_REQUIRES => {
'Test::More' => 0,
},
PREREQ_PM => {
},
dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', },
clean => { FILES => 'RPi-ADC-MCP3008-*' },
);