I am working on a library to read Serial data from an electric counter. The counter can transmit up to 105 different tags depending on your contract. Because this library could be on lightweight and not powerful embedded systems (typically arduino or esp8266), I was wondering if it was possible to have something that would let the user ask only for the tags he is interested in, so that the library would not compile unecessary variables declaration and getter.
For the record, I am new to C and C, but not to the programming world. I build my code using platformIO tool "build".
So far, I have each method and variable declaration for each and every 105 tags. Each tag is decoded in a big switch case statement in a separate file.
file.cpp
#include "LinkyTIC.cpp"
constexpr unsigned int hash(const char* str, int h = 0){
return !str[h] ? 5381 : (hash(str, h 1) * 33) ^ str[h];
}
void substring(char* str, const char* _buffer_value, const int length){
for(int i = 0; i < length; i ){
str[i] = _buffer_value[i];
}
}
switch (hash(tag_name)){
#ifdef ADCO
case hash("ADCO"):{
substring(_ADCO, buffer_value, 12);
break;
}
#endif
#ifdef OPTARIF
case hash("OPTARIF"):{
substring(_OPTARIF, buffer_value, 4);
break;
}
#endif
#ifdef ISOUSC
case hash("ISOUSC"):{
char _tmp[2];
substring(_tmp, buffer_value, 2);
_ISOUSC = atoi(_tmp);
break;
}
#endif
#ifdef BASE
case hash("BASE"):{
char _tmp[9];
substring(_tmp, buffer_value, 9);
_BASE = atol(_tmp);
break;
}
#endif
//...
file.h
public:
#ifdef ADCO
char* GetADCO(){return _ADCO;};
#endif
#ifdef OPTARIF
char* GetOPTARIF(){return _OPTARIF;};
#endif
#ifdef ISOUSC
uint8_t GetISOUSC(){return _ISOUSC;};
#endif
#ifdef BASE
uint32_t GetBASE(){return _BASE;};
#endif
//...
private:
#ifdef ADCO
char _ADCO[12];
#endif
#ifdef OPTARIF
char _OPTARIF[4];
#endif
#ifdef ISOUSC
uint8_t _ISOUSC;
#endif
#ifdef BASE
uint32_t _BASE;
#endif
//...
On the user end, the library is used as the following:
#include <Arduino.h>
#include "LinkyTIC.h"
#include <SoftwareSerial.h>
SoftwareSerial LinkySerial(13, 15);
LinkyTIC linky(LinkySerial);
#define ADCO
#define BASE
void setup() {
}
void loop() {
if(linky.read()){
linky.GetHCHP();
linky.GetOPTARIF();
linky.GetBASE();
}
}
I tried using #ifdef
around each declaration, property and switch case but, for instance, when I included #define BASE
in my main.cpp it had no impact on the filled RAM and flash memory. I guess it wasn't compiling anything between my ifdef.
My second guess was that the compiler would be smart enough to only compile everything related to used methods (like GetBASE()), but it was always compiling everything and filled a whole 1.2kB of RAM (and 6kB of flash).
Is there any way to only compile everything the user will need, but not the rest ?
CodePudding user response:
I think that the problem is that you first #include
your library and #define
your tag specification afterwards.
The compiler 'works' on the library code before you defined the tags you want, so none of the #ifdef
statements were true.
Try defining your tags before including the library.