How to pass a class to a function

I'll try to post this in a clear way, despite my poor english and the poorer C (class) knowledge.
I have a number of Adafruit NeoPixel objects (they are classes, right?).
I wrote some functions that make lighting effects and now I'd need to call these functions passing as argument the name / class /object to act upon.
This is brief code example, where the MakeCross function has to be called for different objects:

#include <Adafruit_NeoPixel.h>
Adafruit_NeoPixel pixels8(NUMPIXELS8, PIN8, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixels16(NUMPIXELS16, PIN16, NEO_GRB + NEO_KHZ800);

uint8_t colIndex = 0;
uint32_t currColor;

uint32_t col[NUMCOLORS] = {
  pixels8.Color(255, 0, 0),     // Red
  pixels8.Color(0, 255, 0),     // Green
  pixels8.Color(0, 0, 255),     // Blue
};


void setup() {
  pixels8.begin();  // INITIALIZE NeoPixel strip object (REQUIRED)
  pixels8.setBrightness(BRIGHT);
  pixels16.begin();  // INITIALIZE NeoPixel strip object (REQUIRED)
  pixels16.setBrightness(BRIGHT);
  ...
  }
  
void loop() {
  currColor = col[colIndex];
  
  MakeCross(pixels8, currColor);  //HERE IS THE CRITICAL ISSUE...
  MakeCross(pixels16, currColor);
  
  colIndex++;
  if (colIndex == NUMCOLORS) colIndex = 0;
  delay(fxDelay);
  
 }
 
void MakeCross(Adafruit_NeoPixel pix, uint32_t c) {  // ... AND / OR HERE
  pix.clear();
  pix.setPixelColor(0, c);
  pix.setPixelColor(2, c);
  pix.setPixelColor(4, c);
  pix.setPixelColor(6, c);
  pix.show();
}

Actually I do not have error from the IDE, but the function does not do anything as if it is never called.
I'm sure there is a way to do it, please tell me, thanks

may be you want a REFERENCE to one of your Neopixel objects?

void MakeCross(Adafruit_NeoPixel &pix, uint32_t c) 

see the &

1 Like

the language is C++
Adafruit_NeoPixel is a class
pixels8 and pixels16 are objects

the same code works, if put in loop? how much is fxDelay?

Absolutely, pass a reference.

You definitely don't want to do this:

void MakeCross(Adafruit_NeoPixel pix, uint32_t c) {

That attempts to make copy of the object you're passing (also known as "pass by value"). That's wasteful of resources when large objects are involved.

It's even worst for the Adafruit_NeoPixel class because it uses dynamic allocation for the pixel memory. The class has no custom Copy Constructor. The Adafruit author should have provided one or specified the Copy Constructor as deleted. Then your code would have caused a compiler error and you would have known something was wrong.

It was so simple :confounded:
What a shame
Thanks

The change to your code was simple. The the implications of using a Reference are profound. You need to study them if you wish to advance farther in your C++ coding.

That is why in my classes I always declare the assignment operator and copy constructor as private. This will cause a compile error if use is attempted. My feeling is if you want to support those operations you should provide the functions rather than rely on the defaults. For example in my PW_INA219 library.

private:
 PW_INA219(const PW_INA219& that);  // disallow copy constructor
 PW_INA219& operator=(const PW_INA219& that);  // disallow assignment operator
1 Like

I second that. One major pitfall of the unintended use of copy is that any changes made to the copy are thrown away on return. This can cause confusion if the function called was expected to change the original.

To make things even more confusing, the reverse is true with the Adafruit_NeoPixel class since it uses dynamically-allocated memory to store the actual pixel data. When passed by value, the default constructor will make a shallow copy. So, the copy's internal pointer will point to the same memory block as the original's. That means changes made to the copy's pixel data in the function will change the original's pixel data because they are the same data.

so I wonder why the copy didn't work

Who knows? As posted, @orionis's code doesn't even compile.

.
one who complains about other libraries is for sure able to remove 3 dots ...
SCNR
:wink:

The posted code contains undefined symbols.

// BAD EXAMPLE - don't use 
#include <Adafruit_NeoPixel.h>
Adafruit_NeoPixel pixels8(8, 8, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixels16(16, 16, NEO_GRB + NEO_KHZ800);

uint8_t colIndex = 0;
uint32_t currColor;

uint32_t col[3] = {
  pixels8.Color(255, 0, 0),     // Red
  pixels8.Color(0, 255, 0),     // Green
  pixels8.Color(0, 0, 255),     // Blue
};


void setup() {
  pixels8.begin();  // INITIALIZE NeoPixel strip object (REQUIRED)
  pixels8.setBrightness(7);
  pixels16.begin();  // INITIALIZE NeoPixel strip object (REQUIRED)
  pixels16.setBrightness(7);
  //...
  }
  
void loop() {
  currColor = col[colIndex];
  
  MakeCross(pixels8, currColor);  //HERE IS THE CRITICAL ISSUE...
  MakeCross(pixels16, currColor);
  
  colIndex++;
  if (colIndex == 3) colIndex = 0;
  delay(420);
  
 }
 
void MakeCross(Adafruit_NeoPixel &pix, uint32_t c) {  // ... AND / OR HERE
  pix.clear();
  pix.setPixelColor(0, c);
  pix.setPixelColor(2, c);
  pix.setPixelColor(4, c);
  pix.setPixelColor(6, c);
  pix.show();
}

I'm sad since sometimes I do not understand the spirit of some comments.
I never said that the posted code was made to compile and run, but only to make evident how I defined the function (MakeCross) and how I invoke it.
It is obvious that there are missing pieces not directly involved in the function call.
If I did something wrong please accept my apologies.

No, nothing wrong. It's just from what you wrote under the posted code .....

...... I concluded that was the actual code that you ran. So, it was surprising that it wouldn't even compile.

Ok, everything cleared

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