Assigning a value in a struct, then can't read it in other namespace... perhaps

Hi,

I can't explain my bug, but I can showing my source code and telling what it is wrong :confused:

Core.h

struct intf
{
  const byte pin;
  uint8_t value;
};

namespace Core {
  static intf connexions[] = {
    { 13, 0 }
  };
}

Core.cpp

namespace Core {
  
  void processLine()
  {
    uint8_t pin, value;
      LOG("GET pin #13"); LOG(" -> "); LOG(connexions[0].value); LOGLN(';');
    if (_currentStream->available()) {
      _readUint8(pin);
      _readUint8(value);
      setValueAtPin(pin, value);
    }
      LOG("SET pin #13"); LOG(" <- "); LOG(connexions[0].value); LOGLN(';');
  }

  boolean setValueAtPin(uint8_t pin, uint8_t value)
  {
    for (uint8_t i=0; i<connexions_len; i++) {
      if (connexions[i].pin == pin) {
        connexions[i].value = value;
        return true;
      }
    }
    return false;
  }
  
}

UsbModule.cpp

namespace UModule {

  void check()
  {
    if (Serial.available()) {
      LOGLN(">>> USB");
      Core::setStream(&Serial);
      LOG("Vb="); LOGLN(connexions[0].value);
      Core::processLine();
      LOG("Va="); LOGLN(connexions[0].value);
      LOGLN("<<< USB");
    }
  }

}

And my log is:

I sent "13=255":

USB
Vb=0
GET pin #13 -> 0;
SET pin #13 <- 255;
Va=0
<<< USB
I sent "13=127":
USB
Vb=0
GET pin #13 -> 255;
SET pin #13 <- 127;
Va=0
<<< USB

Why my reading value in the UModule's namespace is 0? Not null, because if my default value is 63, I always read 63.

And, if I remove "static" before " intf connexions[]" in Core.h, I fail with many errors as: "multiple definition of `Core::pulses'". I think it is not the good way.

Thanks for your help!

Can you post the sketch that implements all of this?

Ok, this is my sketch.ino

#include "Core.h"
#include "config.h"
#include "macros.h"
#include "FastTimer.h"
#include <SPI.h>



#if defined(USB_SPEED) //&& !DEBUG
#include "USlave.h"
#define USE_USB 1
#else
#define USE_USB 0
#endif




void setup()
{
#if USE_USB
  USlave::begin();
#elif DEBUG
  Serial.begin(9600);
#endif
  LOGLN("=== BEGIN SETUP ===");
  Core::setup();
  LOGLN("=== END SETUP ===");
}


void loop()
{
#if USE_USB
  USlave::check();
#endif

  
  // UNCHECK
#if USE_USB
  USlave::uncheck();
#endif
}

Core.cpp

namespace Core {
  
  void setup()
  {
    for (uint8_t i=0; i<connexions_len; i++) {
      //pinMode(connexions[i].pin, OUTPUT);
    }
  }
}

Damned!

I can get the correct value by adding a "uint8_t getValueAtIndex(uint8_t index)"; function in Core.cpp and calling it.

What is the difference between:

  • Core.h: namespace Core { uint8_t getValueAtIndex(uint8_t index) { return connexions[index].value; } }

And:

  • Core.h: namespace Core { uint8_t getValueAtIndex(uint8_t index); }
  • Core.cpp: namespace Core { uint8_t getValueAtIndex(uint8_t index) { return connexions[index].value; } }

In the first case it is an inline function?
Or both are identical?

yggdrasilien:
Core.cpp

namespace Core {

void processLine()
  {
    uint8_t pin, value;
      LOG("GET pin #13"); LOG(" -> "); LOG(connexions[0].value); LOGLN(';');
    if (_currentStream->available()) {
      _readUint8(pin);
      _readUint8(value);
      setValueAtPin(pin, value);
    }
      LOG("SET pin #13"); LOG(" <- "); LOG(connexions[0].value); LOGLN(';');
  }

boolean setValueAtPin(uint8_t pin, uint8_t value)
  {
    for (uint8_t i=0; i<connexions_len; i++) {
      if (connexions[i].pin == pin) {
        connexions[i].value = value;
        return true;
      }
    }
    return false;
  }
 
}




...

Core.cpp

namespace Core {
 
  void setup()
  {
    for (uint8_t i=0; i<connexions_len; i++) {
      //pinMode(connexions[i].pin, OUTPUT);
    }
  }
}

Now I'm totally confused. What does Core.cpp have in it, exactly? What you posted first? Or second?

Why do you want to use namespace at all? It adds unneeded complexity to an Arduino sketch.

Yeah, I think I will remove the namespaces from my project…

But, as I include some extern libraries I would like protecting my variable names.
Moreover, I don't use Class while it is possible. I have nothing to instantiate.

Yes, well you didn't answer my question.

Assigning a value in a struct, then can't read it in other namespace ...

C++ works, you know. Your code, which you confusingly posted in different formats, neither proves nor disproves your assertion.

Sorry, I have lot of files and functions.
I copy/paste only functions which are called. Yes, my code is an aggregation of the 2 quotes here :blush:

namespace Core {
  static intf connexions[] = {
    { 13, 0 }
  };
}

The static is forcing internal linkage on 'connexions', USBModule receives its own copy of the static data. This is better achieved through an unnamed namespace rather than the static keyword. But seeing as this is not what you want, you should read up on the extern keyword.