PDA

View Full Version : Function not Declared in This Scope error (However I believe I have declared it.....)



marinskye
11th April 2016, 22:59
Hi folks,
I have got what I believe is a very basic question. I get an error saying that the function 'pabort' was not declared in this scope when another function tries to use it.
I am running some code, there's quite a few different files that are involved in the compilation but the two relevant to my error are a header file titled 'adcreader.h' and an implementation file titled 'adcreader.cpp'.

The adcreader.cpp file is:




#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
#define MAX_SAMPLES 65536

void ADCreader::pabort(const char *s)
{
perror(s);
abort();
}





ADCreader::ADCreader()
{
int ret = 0;
int fd;
/// int sysfs_fd;

// int no_tty = !isatty( fileno(stdout) );

// set up ringbuffer
samples = new int[MAX_SAMPLES];
// pointer for incoming data
pIn = samples;
// pointer for outgoing data
pOut = samples;
//SPI Constants
static const char *device = "/dev/spidev0.0";
static uint8_t mode = SPI_CPHA | SPI_CPOL;
static uint8_t bits = 8;
static int drdy_GPIO = 22;

//Open SPI Device
fd = open(device, O_RDWR);
if (fd < 0)
pabort("can't open device");

/*
* spi mode
*/
ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
if (ret == -1)
pabort("can't set spi mode");

ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
if (ret == -1)
pabort("can't get spi mode");

/*
* bits per word
*/
ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
if (ret == -1)
pabort("can't set bits per word");

ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
if (ret == -1)
pabort("can't get bits per word");

fprintf(stderr, "spi mode: %d\n", mode);
fprintf(stderr, "bits per word: %d\n", bits);

// enable master clock for the AD
// divisor results in roughly 4.9MHz
// this also inits the general purpose IO
gz_clock_ena(GZ_CLK_5MHz,5);

// enables sysfs entry for the GPIO pin
gpio_export(drdy_GPIO);
// set to input
gpio_set_dir(drdy_GPIO,0);
// set interrupt detection to falling edge
gpio_set_edge(drdy_GPIO,"falling");
// get a file descriptor for the GPIO pin
sysfs_fd = gpio_fd_open(drdy_GPIO);

// resets the AD7705 so that it expects a write to the communication register
printf("sending reset\n");
writeReset(fd);

// tell the AD7705 that the next write will be to the clock register
writeReg(fd,0x20);
// write 00001100 : CLOCKDIV=1,CLK=1,expects 4.9152MHz input clock
writeReg(fd,0x0C);

// tell the AD7705 that the next write will be the setup register
writeReg(fd,0x10);
// intiates a self calibration and then after that starts converting
writeReg(fd,0x40);
}




void ADCreader::writeReset(int fd)
{
int ret;
uint8_t tx1[5] = {0xff,0xff,0xff,0xff,0xff};
uint8_t rx1[5] = {0};
struct spi_ioc_transfer tr;

memset(&tr,0,sizeof(struct spi_ioc_transfer));
tr.tx_buf = (unsigned long)tx1;
tr.rx_buf = (unsigned long)rx1;
tr.len = sizeof(tx1);

ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1) {
printf("\nerr=%d when trying to reset. \n",ret);
pabort("Can't send spi message");
}
}


void writeReg(int fd, uint8_t v)
{
int ret;
uint8_t tx1[1];
tx1[0] = v;
uint8_t rx1[1] = {0};
struct spi_ioc_transfer tr;

memset(&tr,0,sizeof(struct spi_ioc_transfer));
tr.tx_buf = (unsigned long)tx1;
tr.rx_buf = (unsigned long)rx1;
tr.len = sizeof(tx1);

ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1)
pabort("can't send spi message");
}

uint8_t ADCreader::readReg(int fd)
{
int ret;
uint8_t tx1[1];
tx1[0] = 0;
uint8_t rx1[1] = {0};
struct spi_ioc_transfer tr;

memset(&tr,0,sizeof(struct spi_ioc_transfer));
tr.tx_buf = (unsigned long)tx1;
tr.rx_buf = (unsigned long)rx1;
tr.len = sizeof(tx1);

ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1)
pabort("can't send spi message");

return rx1[0];
}

int ADCreader::readData(int fd)
{
int ret;
uint8_t tx1[2] = {0,0};
uint8_t rx1[2] = {0,0};
struct spi_ioc_transfer tr;

memset(&tr,0,sizeof(struct spi_ioc_transfer));
tr.tx_buf = (unsigned long)tx1;
tr.rx_buf = (unsigned long)rx1;
tr.len = sizeof(tx1);

ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1)
{
printf("\n can't send spi message, ret = %d\n",ret);
exit(1);
}

return (rx1[0]<<8)|(rx1[1]);
}




void ADCreader::run() //triggered when thread is started
// we read data in an endless loop and display it
// this needs to run in a thread ideally
{
int ret;
int sysfs_fd;
int no_tty = !isatty( fileno(stdout) );


while (1) {

fprintf("We are running!\n");

// let's wait for data for max one second
ret = gpio_poll(sysfs_fd,1000);
if (ret<1) {
fprintf(stderr,"Poll error %d\n",ret);
}

// tell the AD7705 to read the data register (16 bits)
writeReg(fd,0x38);
// read the data register by performing two 8 bit reads
int value = readData(fd)-0x8000;
fprintf(stderr,"data = %d \r",value);
// qDebug << value;

//*pIn = value;
// if (pIn == (&samples[MAX_SAMPLES-1]))
// pIn = samples;
//else
//pIn++;
// if stdout is redirected to a file or pipe, output the data
if( no_tty )
{
printf("%d\n", value);
fflush(stdout);
}
}

close(fd);
gpio_fd_close(sysfs_fd);

//return ret;
}

int ADCreader::getSample()
{
assert(pOut!=pIn);
int value = *pOut;
if (pOut == (&samples[MAX_SAMPLES-1]))
pOut = samples;
else
pOut++;
return value;
}

int ADCreader::hasSample()
{
return (pOut!=pIn);
}

void ADCreader::quit()
{
running = false;
exit(0);
}



and the adcreader.h file is:



class ADCreader : public QThread //taking this class and inheriting QThread,
//Qthread has a bpublic function called run
{
public:
ADCreader();

// ring buffer functions
int hasSample();
int getSample();


public:
// thread functions
void quit();
void run(); //when we start thread, this is the function going to be called.

protected:
void writeReset(int fd);
void writeReg(int fd, uint8_t v);
uint8_t readReg(int fd);
int readData(int fd);
//int gz_clock_ena(int, int);
private:
bool running;
void pabort(const char *s);

// file descriptor on the SPI interface
int fd;

// file descriptor on the interrupt pin
int sysfs_fd;

// data collected
int *samples;

// pointer to ringbuffer
int *pIn;
int *pOut;

// spi constants for the ioctrl calls
uint8_t mode;
uint8_t bits;
uint32_t speed;
uint16_t delay;
int drdy_GPIO;

};

#endif


When compiling I get the following error:

'adcreader.cpp: In function ‘void writeReg(int, uint8_t)’:
adcreader.cpp:160:36: error: ‘pabort’ was not declared in this scope
pabort("can't send spi message");'

From my code, I can't understand why I would get the error as I had declared it in the header file and declared it in the '.cpp' file. Any help would be greatly appreciated.

Thanks,
Martin

d_stranz
11th April 2016, 23:14
"writeReg" is a standalone function. It is not a member of the ADCreader class, therefore it cannot call non-static member functions of the ADCreader class without using an instance of that class. The compiler is telling you that there is no standalone function called "pabort()", which is true. If you want to call the pabort() method of ADCreader, you have to do it through an instance of that class:



ADCreader myReader;
myReader.pabort( "Whatever" );

// or

ADCreader * myReader = new ADCreader;
myReader->pabort( "Whatever" );
delete myReader;


Probably you don't want to do either of these alternatives, because it is likely you have a global instance of ADCreader that you are using in your program, and that's the one you want to call pabort(). If it isn't visible in the same scope as writeReg(), then you can make it visible by passing it as an argument to writeReg() (preferred) or declaring the global instance as an "extern ADCreader * myGlobalReader;" and ensuring that your global instance is named the same thing and assigned properly.

I think it would be useful to you to learn to walk in C++ before you run while holding a RaspberryPi. Get a C++ book, learn about classes, scoping, and the like, then have at it.

--Edit--

Actually, it looks like you just forgot to make writeReg() a member function of ADCreader, since you have a "readReg" member function already. Still, you need to learn more C++ so you can recognize what it means when your compiler points out these errors to you.

anda_skoa
11th April 2016, 23:38
You probably wanted to have writeReg as a member function like the others.
You even have the prototype declared like one, but your implementation is missing the class name, so it is, as d_stranz said, a stand alone function.

So add the ADCreader:: prefix in front of writeReg and it should build.

Cheers,
_