dinamic store void pointer array

Hi,
I need to store void pointers into a dinamically growing array.
Basicly my code working but I'm not sure of it.
My test code is the following.

void (**voidsArray)(uint8_t);
int eventCount = 0;

void setup() {
  Serial.begin(57600);
  Serial.println("setup");
  addVoid(func1);
  addVoid(func2);
  addVoid(func3);
}

void loop() {
  //test
  voidsArray[0](0);
  voidsArray[1](1);
  voidsArray[2](3);
  delay(1000);
}

void addVoid(void (*ev)(uint8_t)) {
  eventCount += 1;
//IS THE FOLLOWING LINE CORRECT????
  voidsArray  = (void(**)(uint8_t))realloc(voidsArray, sizeof(void (*)) * eventCount);

  voidsArray[eventCount - 1] = ev;
}

void func1(uint8_t v) {
  Serial.println(v);
  Serial.println("ok1");
}
void func2(uint8_t v) {
  Serial.println(v);
  Serial.println("ok2");
}
void func3(uint8_t v) {
  Serial.println(v);
  Serial.println("ok3");
}

output:
setup
0
ok1
1
ok2
3
ok3

Thank you

What Arduino are you using?

It is generally not a good idea to have dynamically sized arrays in the small memory of an Arduino - it can lead to memory corruption. Better to make a fixed array that is big enough for the largest amount of data you will need.

...R

Hi Robin2,

Thank you for answer. I'm using Arduino Due but my full code will contain about 128 pcs such a dynamic array.
Each of them contain 1 - max 4 elements. I'm not sure how mutch memory need my dynamic arry.
I cannot resize this format:
void (voidsArray[1])(uint8_t);
If I use fixed void (voidsArray[4])(uint8_t); it take 1282
4=1024 1kb but you are right due has 96Kb
:o

thank you

If you cannot use a fixed sized array because it uses too much memory then I don't see how you can work round it by using a dynamically sized array. What is going to happen when you resize it and run out of memory ?

my full code will contain about 128 pcs such a dynamic array.

Are you saying that your code will have 128 different arrays ?

how many different functions do you have really ? why would you store the full function pointer each time ? why not keep an array of functions and only store the index of the callback... if you have 16 functions, you could store the index only on 4 bits for example. So to store 128 arrays of up to 4 pointers would require only 256 bytes

here is an example

typedef void(*t_funcCallBack)(uint8_t);

struct t_smallIndexRecord {
  uint8_t idx0: 4;
  uint8_t idx1: 4;
  uint8_t idx2: 4;
  uint8_t idx3: 4;
} ;

const uint8_t maxArrays = 128;
t_smallIndexRecord allArrays[maxArrays];


void func1(uint8_t x) {
  Serial.print(F("In func1, x= "));
  Serial.println(x);
}
void func2(uint8_t x) {
  Serial.print(F("In func2, x= "));
  Serial.println(x);
}
void func3(uint8_t x) {
  Serial.print(F("In func3, x= "));
  Serial.println(x);
}
void func4(uint8_t x) {
  Serial.print(F("In func4, x= "));
  Serial.println(x);
}
void func5(uint8_t x) {
  Serial.print(F("In func5, x= "));
  Serial.println(x);
}
void func6(uint8_t x) {
  Serial.print(F("In func6, x= "));
  Serial.println(x);
}
void func7(uint8_t x) {
  Serial.print(F("In func7, x= "));
  Serial.println(x);
}
void func8(uint8_t x) {
  Serial.print(F("In func8, x= "));
  Serial.println(x);
}
void func9(uint8_t x) {
  Serial.print(F("In func9, x= "));
  Serial.println(x);
}

t_funcCallBack callbacks[] = {
  NULL,
  func1, func2, func3,
  func4, func5, func6,
  func7, func8, func9
};
const uint8_t nbCallBacks = sizeof callbacks / sizeof callbacks[0];

uint8_t getCallBackIndex(t_funcCallBack f)
{
  uint8_t index = 0;
  for (index = 0; index < nbCallBacks; index++) {
    if (callbacks[index] == f) return index;
  }
  return 0;
}


bool addCallback(uint8_t arrayNumber, uint8_t idxID, t_funcCallBack func)
{
  if (arrayNumber >= maxArrays) return false;
  if (idxID >= 4) return false;

  uint8_t index = getCallBackIndex(func);
  if (index == 0) return false;
  switch (idxID) {
    case 0: allArrays[arrayNumber].idx0 = index; break;
    case 1: allArrays[arrayNumber].idx1 = index; break;
    case 2: allArrays[arrayNumber].idx2 = index; break;
    case 3: allArrays[arrayNumber].idx3 = index; break;
    default: break; // won't happen
  }
  return true;
}

void setup() {
  Serial.begin(115200);

  Serial.print(F("Size of t_smallIndexRecord: "));
  Serial.print(sizeof(t_smallIndexRecord));
  Serial.println(F(" bytes"));

  Serial.print(F("Size of allArrays: "));
  Serial.print(sizeof(allArrays));
  Serial.println(F(" bytes"));

  addCallback(0, 0, func3);
  addCallback(0, 1, func7);


  callbacks[allArrays[0].idx0](10);  // also OK written as (*(callbacks[allArrays[0].idx0]))(10);
  callbacks[allArrays[0].idx1](70);
}


void loop() {}

Serial Monitor (@ 115200 bauds) will show

[color=purple]
Size of t_smallIndexRecord: 2 bytes
Size of allArrays: 256 bytes
In func3, x= 10
In func7, x= 70
[/color]

Why not have a base class that's a linked list object and inherent that for each of the functions? Then the functions could link themselves into a list. No more worry about function pointers and all that entails. Also, why do they need to be in a list? What's the big plan here?

-jim lee

BTW,
Your array is not storing "void pointers". It's an array of function pointers. The signature of said functions is that they take a uint8_t argument and return no value. The reason you're doing what you're doing the way you're doing it is still rather unclear.

My projekt a bit complex
I use interrupted MCP23017 io expanders for inputs with Arduino due.
Max 8 ic can use on one wire line it is max 8x16=128 inputs
Other wire (wire1) also able to have 8 ic so I can have max total 256 inputs
(Each channel interrupted! I dont have speed problem!)
Each input has a possibility to register dynamically calback functions from different classes
For ex:
input 1 has only one registred callback function for a Dimmer class
input 2 has two callbacks for two Dimmer classes because one input handle two Dimmers
input 3 has has 6 callbacks for Shutter classes
or mix them with different event handlers like click, doble click, hold, double hold...
and so on...
This looks like working solution for dinamic growing function pointer array:

int counter = 0;
void(**fn)(uint8_t);

void add(void(*_fn)(uint8_t)) {
  counter++;
  if (counter == 1) {
    fn = (void(**)(uint8_t))malloc(sizeof(*fn) * counter);
    fn[0] = _fn;
  } else {
    fn = (void(**)(uint8_t))realloc(fn, sizeof(*fn) * counter);
    fn[counter - 1] = _fn;
  }
}

I know it doesen't a know safe solution

So you configure your system for a max number of input (128 or 256) and you want to attach different behaviors to each input with a Max of 4 things to trigger per input.

So you’ll use up to 4x256=1024 entries to store the behaviors.
Depending on how many bytes you’ll require 0.5, 1, 2 for the behaviors is left up to you - there are ideas listed previously - but point is that it should easily fit in your 96k

So why do you want to go through the Alloc /realloc game? At the end of the day if you use your system to its full capacity you’ll need the memory anyway so better make sure it’s there from the start. It will also make access code much easier - everything can be indexed in an array of struct for example - and if you use indexing tables for the functions as proposed above you can also store the array of struct in EEPROM easily if that is a need to save configurations

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