3

I have a program where a device registers itself with a command object. The command object is losing track of the registrations. The following program repeats "0 devices registered" even though when it initializes it displays "Devices registered 1". My guess is that I am accidentally creating 2 copies of the command object. This is the main sketch

#include "command.h"
#include "widget.h"

Command command;
Widget widget;
void setup() {
  command.init();
  widget.init(command);
}

void loop() {
  command.update();
}

command.h

#include "Arduino.h"

#ifndef Command_h
#define Command_h

typedef struct  {
  char id;
  char name[20];
} Device;

class Command
{
  public:
    Command();
    void init();
    void registerDevice(Device _cmd);
    void update();
  private:
    Device Devices[20];
    byte DevicesPtr = 0;
};

#endif 

command.cpp

#include <Arduino.h>
#include "command.h"

#define DEVICES_MAX 9

Command::Command() {
  DevicesPtr = 0;
  Device Devices[DEVICES_MAX];
}

void Command::init() {
  Serial.begin(9600);
}

void Command::update(){
  Serial.print( DevicesPtr );
  Serial.println( " devices registered" );
  delay(500);  
}
void Command::registerDevice(Device _cmd) {
  _cmd.id = '0' + (++DevicesPtr);
  Devices[DevicesPtr] = _cmd;
  Serial.print("Devices registered ");
  Serial.println(DevicesPtr);
}

widget.h

#include "Arduino.h"
#include "command.h"

class Widget
{
  public:
    static void init(Command _command);

  private:
};

widget.cpp

#include "widget.h"
#include "command.h"

void Widget::init(Command _command) {
  Device device;
  strcpy(device.name, "Widget #1");
  _command.registerDevice(device);
}
0

1 Answer 1

4

It is all about calling conventions and argument binding. The code is using call-by-value when it should be call-by-reference.

This is call-by-value (the incoming command is not updated, a copy is passed as parameter):

void Widget::init(Command _command)
...
widget.init(command);

This is call-by-reference (a pointer to command is passed as parameter):

void Widget::init(Command* _command)
{
   __command->registerDevice(...);
}
...
widget.init(&command);

Alternative syntax is:

void Widget::init(Command& _command)
{
   _command.registerDevice(...);
}
...
widget.init(command)

Cheers!

2
  • Thank you so much, great Christmas present! The compiler complained about "widget.init(&command)" when I changed it to "widget.init(command)" it worked.
    – CarbonMan
    Commented Dec 25, 2015 at 21:05
  • Typical cut-paste-error :). Thanks! Commented Dec 27, 2015 at 0:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.