Passing pointer to PROGMEM to another function

I have an image stored in PROGMEM as a const char[]. When I pass that array to my image displaying library it works just fine. However, when I attempt to pass the same array as a pointer to a function in a different source file it fails to read.

When I do a quick address check by printing the pointer address, they are not the same, even though the should be.... Here is some example code.

The following seems to work:

#include "img/logo.h" // Contains "static const unsigned char logo[] PROGMEM  = ..."

...

void Display::drawPNG(Point at, const unsigned char *data) {
  png_position = at;

  int8_t rc = png.openFLASH((unsigned char *)logo, sizeof(logo), pngDraw);

  Serial.print("data addr:");
  Serial.println((long)data, HEX);

  Serial.print("logo addr:");
  Serial.println((long)&logo[0], HEX);

  if (rc == PNG_SUCCESS) {
    tft.startWrite();
    png.decode((void *)this, 0);
    tft.endWrite();
  } else {
    Serial.println("Failed...");
    Serial.println(png.getLastError());
  }
}

But this does not:

// File 1
#include "img/logo.h" // Contains "static const unsigned char logo[] PROGMEM  = ..."

void drawLogo(Display &display){
  display.drawPNG({0,0}, logo);
}

// File 2
void Display::drawPNG(Point at, const unsigned char *data) {
  png_position = at;

  int8_t rc = png.openFLASH((unsigned char *)data, sizeof(data), pngDraw);

  Serial.print("data addr:");
  Serial.println((long)data, HEX);

  Serial.print("logo addr:");
  Serial.println((long)&logo[0], HEX);

  if (rc == PNG_SUCCESS) {
    tft.startWrite();
    png.decode((void *)this, 0);
    tft.endWrite();
  } else {
    Serial.println("Failed...");
    Serial.println(png.getLastError());
  }
}

In that last example, the two addresses I get are:

data addr:100214F5
logo addr:1001AF9B

Even though they're supposedly both pointing to the logo[] in logo.h.

My apologies if this is a PROMEM 101 level error, but I'm lost...

Thanks!

Daniel Jackson

Try instead

Serial.println((uint16_t) logo, HEX);

(Assuming you are on a uno or similar)

I think your problem is in the sizeof()
For an array, it returns the size of your image in bytes, and for an array pointer, it returns the size of the pointer itself, which is always two bytes on AVR controllers. So the draw method gets the wrong image size and doesn't work.

When you pass an array by pointer, you need to pass its size at the same time.

Add a data_size parameter to `drawPNG() method:

and call it this way:

void drawLogo(Display &display){
  display.drawPNG({0,0}, logo, sizeof(logo) );
}

@b707 you were spot on. I don't know how I missed that. Passing the size as a size_t fixed it right up.

Side note, I love the username. The Boeing 707 has to be one of the best-looking passenger planes to have ever been made. I especially like the Air Force 1 livery with the polished engine nacelles.

Only flew once on a 707. Scared to death when they started an engine. Then the guy in the next seat told me they had to start the first engine with compressed air and that was what all the noise was!

1 Like

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