How to use library function without creating instance/object

This is probably a noob question but I was messing with this for hours and could not find an answer online. I don’t know if I am searching for this correctly or what.

I was already coding in arduino for a while now and decided it was time to learn about libraries. I already started coding a few simple libraries of my own to experiment and I think I got the basic concept of it. I was looking through other libraries as examples to learn from and I came across something interesting when looking in the arduino SD Listfiles example. To my understanding, to use a class you have to create and object or an instance of it but I wonder how does this code work? It does not create an instance of the SDclass in the main file and yet it still works. I could not get this to work in my own library.

  Listfiles

  This example shows how print out the files in a
  directory on a SD card

  The circuit:
   SD card attached to SPI bus as follows:
 ** MOSI - pin 11
 ** MISO - pin 12
 ** CLK - pin 13
 ** CS - pin 4 (for MKRZero SD: SDCARD_SS_PIN)

  created   Nov 2010
  by David A. Mellis
  modified 9 Apr 2012
  by Tom Igoe
  modified 2 Feb 2014
  by Scott Fitzgerald

  This example code is in the public domain.

*/
#include <SPI.h>
#include <SD.h>

File root;

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  Serial.print("Initializing SD card...");

  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    while (1);
  }
  Serial.println("initialization done.");

  root = SD.open("/");

  printDirectory(root, 0);

  Serial.println("done!");
}

void loop() {
  // nothing happens after setup finishes.
}

void printDirectory(File dir, int numTabs) {
  while (true) {

    File entry =  dir.openNextFile();
    if (! entry) {
      // no more files
      break;
    }
    for (uint8_t i = 0; i < numTabs; i++) {
      Serial.print('\t');
    }
    Serial.print(entry.name());
    if (entry.isDirectory()) {
      Serial.println("/");
      printDirectory(entry, numTabs + 1);
    } else {
      // files have sizes, directories do not
      Serial.print("\t\t");
      Serial.println(entry.size(), DEC);
    }
    entry.close();
  }
}

I was expecting to see something like this in the main file
SDClass SD;

I did dig around in the SD.h file and the only thing I came up with is
extern SDClass SD;

at line 122. I tried this in my own code but it did not work. Can someone please help me?

Again, I am very sorry if this is a beginner question but I am trying to get my head around how libraries work. Also, this is my first post so if I am doing something wrong, advice will be much appreciated.

Here it is:

That makes it global so you can use it from the translation unit of the sketch.

1 Like

Wow thank you so much, I do not know How I missed that

You’re welcome. I’m glad if I was able to be of assistance. Enjoy!
Per

You can do the same in your own library by:
1: Create a global instance in your .cpp file
2: Put the ‘extern’ declaration in your .h file

When you include the .h in your main sketch you can use the name of the global object because the compiler knows that it exists somewhere, what type it is, and that the linker will fill in the address when it links all the files together.

OK, I’m going to ask a newbie question.

Why?

What is the downside to creating an instance of the library in your code?

Not really a direct answer, but that is how it’s done in much of the Arduino infrastructure. How do do you think your sketches are magically able to access objects such as Serial, Wire, SPI, SD, etc without having to instantiate them?

Let’s say you have an object class that represents a hardware resource, like EEPROM. You would not want two separate instances of an EEPROM object because they would both be manipulating the same hardware registers, possibly in conflicting ways. In that case, you want a “singleton”: a kind of object class for which only one instance is allowed. Once you have a singleton there is no need to allow the user to specify their own name for the object. Since the user shouldn’t assign a name to the one instance, they shouldn’t be the one to instantiate the instance.

That’s why. :slight_smile:

I learned something new today- and it’s not even lunchtime…

1 Like

You will see that some other libraries do not do this. For example, Servo. The reason being that there are common valid use cases for having multiple Servo objects

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.