declarations in libraries

IMHO you should not declare variables in .h files.

Why not? It is standard practice, recommended everywhere else.

What about class definitions?

PaulS:
What does your sketch look like? Are you including Ethernet.h in the sketch?

No.... And that was the problem! Thanks

PaulS:

IMHO you should not declare variables in .h files.

Why not? It is standard practice, recommended everywhere else.

What about class definitions?

Uh ? Are you saying class definitions and variable declarations are the same thing ?

As for declaring variables in .h files being standard practice, let's look at EEPROM.h/.cpp:

#ifndef EEPROM_h
#define EEPROM_h

#include <inttypes.h>

class EEPROMClass
{
  public:
    uint8_t read(int);
    void write(int, uint8_t);
};

extern EEPROMClass EEPROM;    // <<< reference to a variable declared elsewhere

#endif
#include <avr/eeprom.h>
#include "Arduino.h"
#include "EEPROM.h"

uint8_t EEPROMClass::read(int address)
{
	return eeprom_read_byte((unsigned char *) address);
}

void EEPROMClass::write(int address, uint8_t value)
{
	eeprom_write_byte((unsigned char *) address, value);
}

EEPROMClass EEPROM;   // <<< variable declaration is in .cpp file

Uh ? Are you saying class definitions and variable declarations are the same thing ?

No, I never said that. I'm asking, if you don't like declaring variables in the header file, how you feel about defining classes in header files.

I'm trying to determine whether to take you seriously.

PaulS:

Uh ? Are you saying class definitions and variable declarations are the same thing ?

No, I never said that. I'm asking, if you don't like declaring variables in the header file, how you feel about defining classes in header files.

I'm sorry, that's nonsense. Declaration != definition. Classes are defined in header files. Variables should be declared in .cpp files.

You didn't comment on the EEPROM example.

PaulS:
I'm trying to determine whether to take you seriously.

I will ignore personal attacks.

(edit: typo)

What does your sketch look like? Are you including Ethernet.h in the sketch?

No.... And that was the problem! Thanks

Eh??? It looks like it is there in your code, in your second post on this thread.

It looks like it is there in your code, in your second post on this thread.

The Ethernet.h files was included in the library, as it needs to be. But, it was not included in the sketch.

The Arduino IDE copies files to another directory for compiling. What it copies are the header files included in the sketch plus the sketch plus any source files that go with the header files, plus any other files in the sketch directory.

What it does not copy are header files referenced in other files in the sketch directory. So, since the sketch didn't include Ethernet.h, that file was not copied to the build directory, so it was not available for the library to include/use, so the symbols defined in it were not available. IPAddress is one of those symbols.

I will ignore personal attacks.

It was not a personal attack. I'm just trying to understand your position. It is not common practice.

So here is the code:

Sketch:

#include <SPI.h>
#include <Ethernet.h>
#include "eth.h"

Eth eth();
void setup(){

}


void loop(){
  
}

eth.h:

#ifndef Eth_h
#define Eth_h

#include <SPI.h>
#include <Ethernet.h>
#include "Arduino.h"

 byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
 IPAddress ip(192,168,1, 177);
 EthernetServer server(80);


class Eth{
 

 public:
void init();

};
#endif

and eth.cpp:

#include "Arduino.h"
#include "eth.h"

void Eth::init(){

  
  
  
}

With the variables declared I get these errors:

eth.cpp.o:eth.cpp:14: multiple definition of `ip'
consRemoteTwo.cpp.o:consRemoteTwo.cpp:11: first defined here
/Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/bin/../lib/gcc/avr/4.3.2/../../../../avr/bin/ld: Disabling relaxation: it will not work with multiple definitions
eth.cpp.o:eth.cpp:14: multiple definition of `server'
consRemoteTwo.cpp.o:consRemoteTwo.cpp:11: first defined here
eth.cpp.o:(.data.mac+0x0): multiple definition of `mac'
consRemoteTwo.cpp.o:(.data.mac+0x0): first defined here

Any suggestions on what I'm still doing wrong?

Thanks again,

Loren

Well, you need to be careful not to define things twice.

That's why most header files have that #ifndef stuff at the beginning, to prevent them being included twice.

Your "variables" mac and server are being defined twice. This could mean one of two things:
(a) the same variable is being included twice, or
(b) two different variables are being defined, using the same name.

To distinguish these cases, try re-naming your instances of these variables to something else. Like mac_xxx and server_xxx.
And then see what happens.

Eth eth();

That is not how to create an instance of the class. Loose the ().

michinyon:
Well, you need to be careful not to define things twice.

That's why most header files have that #ifndef stuff at the beginning, to prevent them being included twice.

Your "variables" mac and server are being defined twice. This could mean one of two things:
(a) the same variable is being included twice, or
(b) two different variables are being defined, using the same name.

To distinguish these cases, try re-naming your instances of these variables to something else. Like mac_xxx and server_xxx.
And then see what happens.

I tried to rename the variables. The same errors are still occurring.

I did lose the () to create the class. No changes in the errors there either.

Please explain why those are global variables (that is why they are created twice), rather than class fields.

You could define the variables in the sketch, and add extern in front of the declaration statements in the header. That way, the header file would simply affirm that the variables are defined somewhere else, and would allow access to them, wherever they are defined.

For those trying to avoid the pain of what I just went through here is what I found:

PaulS:
Please explain why those are global variables (that is why they are created twice), rather than class fields.

You could define the variables in the sketch, and add extern in front of the declaration statements in the header. That way, the header file would simply affirm that the variables are defined somewhere else, and would allow access to them, wherever they are defined.

I didn't necessarily want them to be global variables. After seeing that comment I took another look at the library tutorial and noticed that I should be declaring the variables below with the private declarations for the class:

#ifndef eth_h
#define eth_h

#include <SPI.h>
#include <Ethernet.h>
#include "Arduino.h"
  
class Eth{

public:
void init();

private:
byte mac[5];
};
#endif

I think this will be the last step in helping me figure out how to write libraries. Here is the code as it stands now:

sketch:

#include <SPI.h>
#include <Ethernet.h>
#include "eth.h"

Eth eth;

EthernetServer server(80);

void setup(){
  Serial.begin(9600);
  Serial.println("Setup has begun");
eth.init();
}


void loop(){
  //Serial.println("Loop");
 eth.servClient();
}

eth.h:

#ifndef eth_h
#define eth_h

#include <SPI.h>
#include <Ethernet.h>
#include "Arduino.h"
  



class Eth{


 public:


void init();
void servClient();

private:
byte mac[5];

};
#endif

eth.cpp:

#include "Arduino.h"
#include "eth.h"

void Eth::init(){
 mac[0] = 0xDE;
 mac[1] = 0xAD;
 mac[2] = 0xBE;
 mac[3] = 0xEF;
 mac[4] = 0xFE;
 mac[5] = 0xED;
IPAddress ip(192,168,1,177);
extern EthernetServer server;
  Ethernet.begin(mac, ip);
  server.begin();
 Serial.print("server is at ");
 Serial.println(Ethernet.localIP());
  
}

void Eth::servClient(){
   Serial.print("Server is at:  ");
 Serial.println(Ethernet.localIP());
  //Serial.println("servClient called");
  extern EthernetServer server;
   // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connnection: close");
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<html>");
          client.println("<head><title>Lorens Page</title></head>");
                    // add a meta refresh tag, so the browser pulls again every 5 seconds:
          client.println("<meta http-equiv=\"refresh\" content=\"5\">");
          
          //client.print("Transport is currently:  ");
          //client.print(stat);
          client.println("
");
          // output the value of each analog input pin
          for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
            int sensorReading = analogRead(analogChannel);
            client.print("analog input ");
            client.print(analogChannel);
            client.print(" is ");
            client.print(sensorReading);
            client.println("
");       
          }
          client.println("</html>");
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        } 
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
    Serial.println("client disonnected");
  }

}

Clients are unable to connect to the server. I have a feeling this has something to do with the way that I have declared "EthernetServer server(80)" and the way I'm using extern.

Are the functions "init" and "serveClient" in the Eth class creating their own instance of server?

Again many many thanks!

Loren

Why is the server object created in the sketch? It is not used in the sketch.

That was the only place I could find to create it "Globally" that the source file could see it. Where should it be declared?

Where should it be declared?

As a private field in the class.