Trouble pulling functions out of main program into separate .cpp file

Executive summary:
I try to pull out some routines from my .ino file to a .cpp file but when it gets compiled, it gives me “multiple definitions” errors in a file that is included multiple times. However, I thought that the “ifndef WEBDUINO_H_” structure was designed to protect against that error.

What am I doing wrong?

-------------------------- EXAMPLE CODE BELOW -------------------

This is a super-pared-down version of my sketch. It is not actually capable of doing anything useful, except reproducing the error I’m getting.

The only things you’d need to have besides what I’m posting are the Ethernet library and the “Webduino” library (GitHub - sirleech/Webduino: Arduino WebServer library) , installed as WebServer, so you can include WebServer.h.

If I erred by not posting it, let me know and I can reproduce that file in the forum, but it seemed kind of extravagant to do so…

I’m trying to put setup routines for SDCard, ethernet, webServer, webClient, etc. all into a general-purpose set of initialization routines that I will call “setup.cpp” with a matching header file called “setup.h”.

In my tiny example, WebServer.h must be included by the top-level project, TinyExample.ino, as well as setup.cpp and setup.h, because they all include types in their function prototypes that are declared in WebServer.h.

Yes, WebServer.h does include the “ifndef trick” to avoid re-declaring stuff in the header file.

I get a bunch of “multiple definition” errors all from inside WebServer.h. Here are the first few:

TinyExample.cpp.o: In function `WebServer::setDefaultCommand(void (*)(WebServer&, WebServer::ConnectionType, char*, bool))':
/Users/kebm/Documents/Arduino/libraries/WebServer/WebServer.h:364: multiple definition of `WebServer::setDefaultCommand(void (*)(WebServer&, WebServer::ConnectionType, char*, bool))'
setup.cpp.o:/Users/kebm/Documents/Arduino/libraries/WebServer/WebServer.h:364: 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
TinyExample.cpp.o: In function `WebServer::setFailureCommand(void (*)(WebServer&, WebServer::ConnectionType, char*, bool))':
/Users/kebm/Documents/Arduino/libraries/WebServer/WebServer.h:369: multiple definition of `WebServer::setFailureCommand(void (*)(WebServer&, WebServer::ConnectionType, char*, bool))'
setup.cpp.o:/Users/kebm/Documents/Arduino/libraries/WebServer/WebServer.h:369: first defined here
TinyExample.cpp.o: In function `WebServer::addCommand(char const*, void (*)(WebServer&, WebServer::ConnectionType, char*, bool))':
/Users/kebm/Documents/Arduino/libraries/WebServer/WebServer.h:372: multiple definition of `WebServer::addCommand(char const*, void (*)(WebServer&, WebServer::ConnectionType, char*, bool))'
setup.cpp.o:/Users/kebm/Documents/Arduino/libraries/WebServer/WebServer.h:372: first defined here
TinyExample.cpp.o: In function `WebServer::setUrlPathCommand(void (*)(WebServer&, WebServer::ConnectionType, char**, char*, bool))':

Here are the files in my sketch.

TinyExample.ino:

/* Web_Demo.pde -- sample code for Webduino server library */

#include "Ethernet.h"
#include "WebServer.h"

#include "setup.h"
#define PREFIX ""

WebServer webserver(PREFIX, 80);

void setup() {
  webserver.setDefaultCommand(&defaultCmd);
}

void loop() {
  webserver.processConnection();
}

setup.cpp:

#include "WebServer.h"

void defaultCmd(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete)
{
  return;
}

setup.h:

#include "WebServer.h"

#ifndef SETUP_H_
#define SETUP_H_

void defaultCmd(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete);

#endif // SETUP_H_

Whoever wrote the webduino thingie doesn't have much of a clue about the concepts of a header file.

You never put functions direct in a header file like that for precisely this reason.

The definitions go in the header file, the code goes in a .cpp file.

This is not something you have done wrong, but the fault of the WebServer.h writer.

You do define the class structure in the header file. Maybe you can clean up the webduino code.

http://arduino.cc/en/Hacking/LibraryTutorial

I have raised it as an issue with the writers of the library.