Server on Arduino Ethernet fails

Hello world ! ^^

I’m newbee with Arduino and C++ (but I programmed in Basic, Pascal, and 6809 chips …) so, thanks to be patient ^^

I’ve an Arduino Ethernet (with the chip 328 inside) and I want to melt 2 programs : one named “Teleinfo_Arduino_V0_2_c.ino” and the second named “SDWebBrowse.ino”.
When I verify the first program in the IDE, I obtain no error. XD
When I verify the second program, I obtain this error :
“core.a(new.cpp.o): In function __cxa_pure_virtual': C:\arduino-1.0.1\hardware\arduino\cores\arduino/new.cpp:17: multiple definition of __cxa_pure_virtual’
SdFat\SdStream.cpp.o:C:\arduino-1.0.1\libraries\SdFat/SdStream.cpp:25: first defined here”

I have only the “SDWebBrowse.ino” file in the folder.
All the libraries are in the good folder : SPI, Ethernet, SDFAT last version, Ethernet2, RTC, Wire.
I don’t understand because I found this program on the www.ladyada.net site and was tested. (Arduino Tutorials - Ethernet+SD)
Is there a problem between the Arduino IDE and this program ?

This is the code :

/*
* USERS OF ARDUINO 0023 AND EARLIER: use the 'SDWebBrowse.pde' sketch...
* 'SDWebBrowse.ino' can be ignored.
* USERS OF ARDUINO 1.0 AND LATER: **DELETE** the 'SDWebBrowse.pde' sketch
* and use ONLY the 'SDWebBrowse.ino' file. By default, BOTH files will
* load when using the Sketchbook menu, and the .pde version will cause
* compiler errors in 1.0. Delete the .pde, then load the sketch.
*
* I can't explain WHY this is necessary, but something among the various
* libraries here appears to be wreaking inexplicable havoc with the
* 'ARDUINO' definition, making the usual version test unusable (BOTH
* cases evaluate as true). FML.
*/

/*
* This sketch uses the microSD card slot on the Arduino Ethernet shield
* to serve up files over a very minimal browsing interface
*
* Some code is from Bill Greiman's SdFatLib examples, some is from the
* Arduino Ethernet WebServer example and the rest is from Limor Fried
* (Adafruit) so its probably under GPL
*
* Tutorial is at http://www.ladyada.net/learn/arduino/ethfiles.html
* Pull requests should go to http://github.com/adafruit/SDWebBrowse
*/

#include <SdFat.h>
#include <SdFatUtil.h>
#include <Ethernet.h>
#include <SPI.h>

/************ ETHERNET STUFF ************/
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0x62, 0x40 };
byte ip[] = { 192, 168, 1, 2 };
EthernetServer server(80);

/************ SDCARD STUFF ************/
Sd2Card card;
SdVolume volume;
SdFile root;
SdFile file;

// store error strings in flash to save RAM
#define error(s) error_P(PSTR(s))

void error_P(const char* str) {
  PgmPrint("error: ");
  SerialPrintln_P(str);
  if (card.errorCode()) {
    PgmPrint("SD error: ");
    Serial.print(card.errorCode(), HEX);
    Serial.print(',');
    Serial.println(card.errorData(), HEX);
  }
  while(1);
}

void setup() {
  Serial.begin(9600);
 
  PgmPrint("Free RAM: ");
  Serial.println(FreeRam());
  
  // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
  // breadboards. use SPI_FULL_SPEED for better performance.
  pinMode(10, OUTPUT); // set the SS pin as an output (necessary!)
  digitalWrite(10, HIGH); // but turn off the W5100 chip!

  if (!card.init(SPI_HALF_SPEED, 4)) error("card.init failed!");
  
  // initialize a FAT volume
  if (!volume.init(&card)) error("vol.init failed!");

  PgmPrint("Volume is FAT");
  Serial.println(volume.fatType(),DEC);
  Serial.println();
  
  if (!root.openRoot(&volume)) error("openRoot failed");

  // list file in root with date and size
  PgmPrintln("Files found in root:");
  root.ls(LS_DATE | LS_SIZE);
  Serial.println();
  
  // Recursive list of all directories
  PgmPrintln("Files found in all dirs:");
  root.ls(LS_R);
  
  Serial.println();
  PgmPrintln("Done");
  
  // Debugging complete, we start the server!
  Ethernet.begin(mac, ip);
  server.begin();
}

void ListFiles(EthernetClient client, uint8_t flags) {
  // This code is just copied from SdFile.cpp in the SDFat library
  // and tweaked to print to the client output in html!
  dir_t p;
  
  root.rewind();
  client.println("<ul>");
  while (root.readDir(p) > 0) {
    // done if past last used entry
    if (p.name[0] == DIR_NAME_FREE) break;

    // skip deleted entry and entries for . and ..
    if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.') continue;

    // only list subdirectories and files
    if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue;

    // print any indent spaces
    client.print("<li><a href=\"");
    for (uint8_t i = 0; i < 11; i++) {
      if (p.name[i] == ' ') continue;
      if (i == 8) {
        client.print('.');
      }
      client.print((char)p.name[i]);
    }
    client.print("\">");
    
    // print file name with possible blank fill
    for (uint8_t i = 0; i < 11; i++) {
      if (p.name[i] == ' ') continue;
      if (i == 8) {
        client.print('.');
      }
      client.print((char)p.name[i]);
    }
    
    client.print("</a>");
    
    if (DIR_IS_SUBDIR(&p)) {
      client.print('/');
    }

    // print modify date/time if requested
    if (flags & LS_DATE) {
       root.printFatDate(p.lastWriteDate);
       client.print(' ');
       root.printFatTime(p.lastWriteTime);
    }
    // print size if requested
    if (!DIR_IS_SUBDIR(&p) && (flags & LS_SIZE)) {
      client.print(' ');
      client.print(p.fileSize);
    }
    client.println("</li>");
  }
  client.println("</ul>");
}

// How big our line buffer should be. 100 is plenty!
#define BUFSIZ 100

void loop()
{
  char clientline[BUFSIZ];
  int index = 0;
  
  EthernetClient client = server.available();
  if (client) {
    // an http request ends with a blank line
    boolean current_line_is_blank = true;
    
    // reset the input buffer
    index = 0;
    
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        
        // If it isn't a new line, add the character to the buffer
        if (c != '\n' && c != '\r') {
          clientline[index] = c;
          index++;
          // are we too big for the buffer? start tossing out data
          if (index >= BUFSIZ)
            index = BUFSIZ -1;
          
          // continue to read more data!
          continue;
        }
        
        // got a \n or \r new line, which means the string is done
        clientline[index] = 0;
        
        // Print it out for debugging
        Serial.println(clientline);
        
        // Look for substring such as a request to get the root file
        if (strstr(clientline, "GET / ") != 0) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();
          
          // print all the files, use a helper to keep it clean
          client.println("<h2>Files:</h2>");
          ListFiles(client, LS_SIZE);
        } else if (strstr(clientline, "GET /") != 0) {
          // this time no space after the /, so a sub-file!
          char *filename;
          
          filename = clientline + 5; // look after the "GET /" (5 chars)
          // a little trick, look for the " HTTP/1.1" string and
          // turn the first character of the substring into a 0 to clear it out.
          (strstr(clientline, " HTTP"))[0] = 0;
          
          // print the file we want
          Serial.println(filename);

          if (! file.open(&root, filename, O_READ)) {
            client.println("HTTP/1.1 404 Not Found");
            client.println("Content-Type: text/html");
            client.println();
            client.println("<h2>File Not Found!</h2>");
            break;
          }
          
          Serial.println("Opened!");
                    
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/plain");
          client.println();
          
          int16_t c;
          while ((c = file.read()) > 0) {
              // uncomment the serial to debug (slow!)
              //Serial.print((char)c);
              client.print((char)c);
          }
          file.close();
        } else {
          // everything else is a 404
          client.println("HTTP/1.1 404 Not Found");
          client.println("Content-Type: text/html");
          client.println();
          client.println("<h2>File Not Found!</h2>");
        }
        break;
      }
    }
    // give the web browser time to receive the data
    delay(1);
    client.stop();
  }
}

In SdFatConfig.h comment the following line out:

#define USE_CXA_PURE_VIRTUAL 1

Then your code compiles.

Hello Pylon,

Thank you very much for your response !

I edit the file "SdFatConfig.h" and found the right line. This line was like that (not a comment) :

/**
 * The __cxa_pure_virtual function is an error handler that is invoked when
 * a pure virtual function is called.
 */
#define USE_CXA_PURE_VIRTUAL 1 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#endif  // SdFatConfig_h

So I transform it in :

/**
 * The __cxa_pure_virtual function is an error handler that is invoked when
 * a pure virtual function is called.
 */
// #define USE_CXA_PURE_VIRTUAL 1 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#endif  // SdFatConfig_h

... and the code compiles !

It's miraculous ! ^^

I don't understand what's wrong with this line and the code, but I'm happy to see that the code works.

Thanks a lot !

I don’t understand what’s wrong with this line and the code, but I’m happy to see that the code works.

There is nothing wrong with that line. It’s just that a similar statement appears in some other code, resulting in __cxa_pure_virtual being defined twice.

Commenting it out in SdFatConfig.h means that the symbol, and resulting function, is only defined once, which makes the linker happy.

You could also use this in each library. This would prevent the double define.

#ifndef USE_CXA_PURE_VIRTUAL
  #define USE_CXA_PURE_VIRTUAL 1
#endif

That would prevent a fail if each is used alone.

You could also use this in each library.

You should…

Ok !

Thanks a lot at all of you !

I understand more about the problem !

Your answers are crystal clear !

I haven't seen where was the double definition in the code, but I'm going to modify the "SdFatConfig.h" file with your suggestion.

I'm sorry, but with this modification, the code doesn't compiles ...

"Doesn't compile" doesn't help. What are the errors generated by the compile?

I'm sorry, but with this modification, the code doesn't compiles ...

Bummer. If you showed the changes that you made, and the compiler messages, we could offer more than sympathy.

Oh !

Excuse me !

The end of the file was :

/**
 * The __cxa_pure_virtual function is an error handler that is invoked when
 * a pure virtual function is called.
 */
  #define USE_CXA_PURE_VIRTUAL 1
#endif  // SdFatConfig_h

I transform it into :

/**
 * The __cxa_pure_virtual function is an error handler that is invoked when
 * a pure virtual function is called.
 */
 #ifndef USE_CXA_PURE_VIRTUAL
   #define USE_CXA_PURE_VIRTUAL 1
 #endif
#endif  // SdFatConfig_h

It generates this error message :

core.a(new.cpp.o): In function __cxa_pure_virtual': C:\arduino-1.0.1\hardware\arduino\cores\arduino/new.cpp:17: multiple definition of__cxa_pure_virtual' SdFat\SdStream.cpp.o:C:\arduino-1.0.1\libraries\SdFat/SdStream.cpp:25: first defined here

I didn't notice this before:

I haven't seen where was the double definition in the code, but I'm going to modify the "SdFatConfig.h" file with your suggestion.

It appears by your error message, the other define is in SdStream.cpp, line 25. The compiler says it is first defined there.

If you want this to work, you need to modify both headers with that change. If the header with the modified code is compiled first, it will define that variable name.

If the other header is included after this, you will still get the "double define" error if you don't modify that also.

Yes, clear ! I'm going to modify all the headers in cascade, until the errors comes ...

This program (“SDWebBrowse.ino”) use the SdFatlib :

#include <SdFat.h>
#include <SdFatUtil.h>
/************ SDCARD STUFF ************/
Sd2Card card;
SdVolume volume;
SdFile root;
SdFile file;

and other instructions like :

if (card.errorCode()) {
    PgmPrint("SD error: ");
    Serial.print(card.errorCode(), HEX);
    Serial.print(',');
    Serial.println(card.errorData(), HEX);
if (!card.init(SPI_HALF_SPEED, 4)) error("card.init failed!");
  
  // initialize a FAT volume
  if (!volume.init(&card)) error("vol.init failed!");

The other program use the"SD.h" library :

#include <SD.h>

Can I use only one of those libraries ?
Is SDFat.h more powerfull than SD.h ?
Are the commands of SD.h present in SDFat.h ?
Can I copy and paste the code using SD library into the code using SDFat library without obtaining errors ?
Is there equivalence between some of the headers and .cpp ?

It’s a little bit nebulous for me …

Well, I "mixed" the two codes.

The errors that Arduino IDE returns (I had 15 errors, and now only 3 that I don't understand ...) :

Teleinfo_Webserver_Arduino_V0_2_c:4: error: variable or field 'ListFiles' declared void Teleinfo_Webserver_Arduino_V0_2_c:4: error: 'EthernetClient' was not declared in this scope Teleinfo_Webserver_Arduino_V0_2_c:4: error: expected primary-expression before 'flags'

It seems this line not good : (1st code)

void ListFiles(EthernetClient client, uint8_t flags) {

This code is after :

  EthernetClient client = server.available();
  if (client) {
    // Une requète http se termine par une ligne vide
    boolean current_line_is_blank = true;
    
    // RAZ buffer d'entrée
    index = 0;
    
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();

I can't post the entire code because it's too long (> 9500 char.)

Can you help me ?

I can't post the entire code because it's too long (> 9500 char.)

On the reply page, down there below where you type stuff, there is, in orange, Additional Options...

When you click that, there is an option to attach a file. You can attach up to 4M file. If your sketch is larger than that, it won't work anyway.

Teleinfo_Webserver_Arduino_V0_2_c:4: error: variable or field 'ListFiles' declared void

This means that somewhere you are trying to assign the return value from ListFiles to a variable. Since ListFiles is not defined to return a value, that is not allowed.

Teleinfo_Webserver_Arduino_V0_2_c:4: error: 'EthernetClient' was not declared in this scope

Probably missing an include file, or the code is in the wrong place.

Teleinfo_Webserver_Arduino_V0_2_c:4: error: expected primary-expression before 'flags'

Need to see the code, but somewhere before where flags appears, there is a syntax error.

Hello Paul,

Thank you for your responses.
I attach the .ino file to this post.
It’s not the definitive version : I must simplify the code …

I think that the definition of the ListFiles function generates those errors.
I tried including the EthernetClient ("#include <EthernetClient.h>"), but It solves nothing : I had the same errors :

Teleinfo_Webserver_Arduino_V0_2_c:4: error: variable or field ‘ListFiles’ declared void
Teleinfo_Webserver_Arduino_V0_2_c:4: error: ‘EthernetClient’ was not declared in this scope
Teleinfo_Webserver_Arduino_V0_2_c:4: error: expected primary-expression before ‘flags’

The code generating the errors was just copied and paste from the “SDWebBrowse.ino” code, witch is working properly …

Teleinfo_Webserver_Arduino_V0_2_c.ino (33 KB)

SDWebBrowse.ino (7.31 KB)

The code generating the errors was just copied and paste from the "SDWebBrowse.ino" code, witch is working properly ...

Not a straight copy and paste...

The Arduino IDE adds code to the sketch, for things like function prototypes and necessary include files. It makes the additions after the first line of code in your file. Your first non-comment line is:

char version_logiciel[6] = "V0.2c";

The IDE added function prototypes after this statement, like:

void ListFiles(EthernetClient client, uint8_t flags);

Since this is added BEFORE the EthernetClient include statement, the EthernetClient class is "not declared in this scope". This error caused the line to be ignored. Then, the ListFiles function was actually encountered. Since there was no function prototype, the compiler expected that the function would return an int. It's signature does not match the compiler's expectations, hence the first message.

I'm not sure what the third one is about.

Moving the version_logiciel declaration and initialization AFTER the include files got rid of these three error messages, but introduced a whole slew of new errors. Some of them are because I do not have all the libraries that you do. If you encounter more problems, post the errors (and the modified code).

If I understand your reply, the organization for a sketch is :

1/ #include 2/ #define 3/ Variables declarations (int, byte, char, unsigned, ...) 4/ Functions 5/ Setup 6/ Loop

Is that good ?

Is that good ?

That's almost the way I organize my programs. It plays well with the IDE. Functions can be in any order. The IDE will generate function prototypes for all functions that it can. You may need to manually add some, if you use reference values or templates.

But, the includes should come first.