#ifndef not working as I expect

06 Mar 2011

Hi, I'm trying to consolidate the basics of modular programming techniques, but I'm unsure why the #ifndef compiler directive has no effect....

I've created three files in a project:

//main.cpp
#include "header.h"

int main() {
 
}
//end main.cpp

//functions.cpp
#include "header.h"

//end functions.cpp

//header.h
#ifndef HEADER_H
#define HEADER_H

#include "mbed.h"

char c;

#endif
// end header.h

But I always get a compiler error saying that multiple definitions of char c are attempted. Surely if the #ifndef directive is working ok then the header file would only be invoked once...? Ultimately I want to define all my global mbed objects, variables, #defines and function prototypes in header.h, but I can only do this if it's possible to ensure that the compiler only looks at header.h once. Any ideas?

06 Mar 2011

in header.h you are declaring the storage for char c.

Move that char c; statement to the .c or .cpp file in which it is used.

If char c is to be visible to other modules, you can use the C style statement in the .h file: extern char c;

06 Mar 2011

Rob, I suspect you are actually getting a linker error, although that may not be obvious. As each individual file is compiled, the compiler reads that file and the included file and it successfully creates a memory object 'c'. Neither cpp file knew of the existance of the other cpp file. Then, when the two files were linked together to try to form a program, it found these two things called 'c' but it could not tell that you intended them to be one in the same, so it errors out - multiple definitions.

To bend your code to demonstrate what steve is recommending.

//main.cpp
#include "functions.h"
int main() {
    c = 3;     // c is defined elsewhere, as 'functions.h' tells us
    printc();  // this function is also defined elsewhere
}
//end main.cpp


//functions.cpp
#include "mbed.h"
char c;            // c is 'owned' by this file
void printc() {    // printc is also owned by this file
    printf("c is %i\r\n", c);
}
//end functions.cpp


//functions.h is the "interface" to functions.cpp
#ifndef FUNCTIONS_H
#define FUNCTIONS_H
extern char c;           // indicate that c exists somewhere
extern void printc();    // indicate that printc exists somewhere
#endif // FUNCTIONS_H

So in this variation, main.cpp learns of c and printc from the functions.h header file. Also note that functions.cpp is the only one that needed mbed.h. So each file gets enough information to do what it needs, but not more.

06 Mar 2011

Thanks guys for a quick response - yeah, that's how I've always done it in the past, but for some reason I thought I could define them all in the header. OK, I'll keep going like that, nice to know I'm already doing things the right way :)

26 Apr 2011

Hi , I followed this format but I get another error : " Symbol spi multiply defined (by main.cpp.cpp.LPC1768.o and encoders.cpp.cpp.LPC1768.o). (EL6200E)" in file "/"

also get the same error for cs1, cs2 and pc

This is my effective code

//main.cpp
#include "functions.h"
#include "mbed.h"
int main() {

    void checkCounters() {
    long count[2];
    uint8_t dIn[4];

    Timer clk;

    clk.start();

    cs1 = 0;
    spi.write(0x60);}
  // some more stuff
//end main.cpp


//functions.cpp
#include "mbed.h"

SPI spi(p11, p12, p13); // mosi, miso, sclk
DigitalOut cs1(p14);
DigitalOut cs2(p15);
Serial pc(USBTX, USBRX);

void initializeEncoders() {


// Counter 1
    // clear registers
    
    cs1 = 0;
    spi.write(0x8);  // clear mdr0
    cs1 = 1;
    wait_us(10);
    cs1 = 0;
    spi.write(0x10);  // clear mdr1
    cs1 = 1;
    wait_us(20);
//Some more stuff

//end function.cpp


// FUNCTION.H
#ifndef ENC_H
#define ENC_H

#include "mbed.h"
extern SPI spi(p11, p12, p13); // mosi, miso, sclk
extern DigitalOut cs1(p14);
extern DigitalOut cs2(p15);

extern Serial pc(USBTX, USBRX);
#endif

extern void initializeEncoders();

//end function.h
26 Apr 2011

When using extern don't supply the parameters, otherwise you are creating a new instance rather than defining an external:-

FUNCTION.H

#ifndef ENC_H
#define ENC_H

extern SPI spi;
extern DigitalOut cs1;
extern DigitalOut cs2;

extern Serial pc;
#endif

extern void initializeEncoders();

Also, include mbed.h first, before your own header, otherwise things like Serial, DigitalOut, SPI, etc, are not yet known.

main.cpp

#include "mbed.h"
#include "functions.h"

int main() {
  ...
}