I am working on a project with an ESP32 and a MCP23017.
In the main program I create an object for the MCP and initialize the address.
Adafruit_MCP23X17 pin_Expander;
const int expander_addr = 0x20; // Adress 0x20
void setup()
{
Serial.begin(9600);
pin_Expander.begin_I2C(expander_addr);
expander_Init(pin_Expander);
}
Since I use many IOs in the project, I wanted to outsource the initialization of these and wrote a function. I have created a separate header file for the function.
void expander_Init(Adafruit_MCP23X17 pin_Expander)
{
// Load the GPIOs
pin_Expander.pinMode(pin1_Motor1, OUTPUT); // I have removed the other pins
// Set all GPIOs to LOW
pin_Expander.digitalWrite(pin1_Motor1, LOW); // I have removed the other pins
}
I wonder if this is a legitimate way to pass an object into another function?
Adafruit_MCP23X17
is a C++ class, not some typedef that simulates reference semantics in C, so when you declare your function:
void expander_Init(Adafruit_MCP23X17 pin_Expander)
you're accepting the object by value, not by reference, which means expander_Init(pin_Expander);
copies pin_Expander
and passes in the copy. Any mutations to the copy would not typically affect the original version (unless the class is poorly designed†).
If you want to modify the original version, change the prototype to:
void expander_Init(Adafruit_MCP23X17& pin_Expander)
// ^ added & to make it accept by reference
which means you'll accept a reference to whatever the caller passed, no copies involved, and anything you do to that reference is equivalent to doing it to the original caller-passed object.
† I'll note: I wouldn't be surprised if the class was poorly designed, and all instance methods effectively modified global, not per-instance, state (low-level hardware manipulation can often make assumptions like this), so your original code might work just fine, but it's not guaranteed without source code inspection, and it might involve some inefficiencies in the extra copy-and-destroy work that passing-by-reference avoids.