3

I need to implement callback in my C++ library. The "proper" C++ way of doing it would be to create an interface (or pure abstract class) and pass it to interested party. I'm wondering though, would that be optimal?

My analysis:

  • Function pointer - occupies 2 bytes in memory (+code of function)
  • Class derived from abstract one - occupies 2 bytes in memory PLUS 2 bytes for VMT (since we have derived method) PLUS size of VMT table (if any) (+code of method).

Is optimizer smart enough to compile abstract class with single method as method pointer? Which solution is more optimal in regard of memory and speed? Is my analysis correct?

2
  • You have to choose between size optimization and usability/readability. With a virtual method, you can encapsulate data with the actual code, at the size cost you mentioned. The response will actually depend on how much size you have for your project? – jfpoilpret Jun 25 '17 at 13:36
  • Regarding your optimizer question, it would be better to ask this to GCC people as it is certainly not specific to Arduino. – jfpoilpret Jun 25 '17 at 13:36
4

Sometimes you want your callback to be fed some data that you provide when you register that callback. Here is a very common callback pattern in plain C that does that:

// The API:

typedef void (*callback_t)(void *data);
void register_callback(callback_t callback, void* data);

// Usage:

typedef struct {
    // stuff only the user of the API knows about.
} my_data_t;

void my_callback(void *in_data)
{
    my_data_t *data = (my_data_t *) in_data;
    // do something with data->foo, data->bar...
}

// ...somewhere else:
my_data_t my_data = { stuff... };
register_callback(my_callback, (void *)&my_data);

The problem is: it's clumsy. C++ classes allow you to pack together the code (the callback function) and the data it needs. Thus, if in your use case you need to pass data to the callback, by all means use a C++ class. It will make your life easier and you are unlikely to even notice the memory overhead.

However, if you only need to pass a function, with no attached data, then a plain function pointer would be both easier for the API user and optimal memory-wise.

2

The best way is to find out yourself, there are memory 'debug' functions to show the amount of free memory, so if you do some tests you know for sure what the compiler optimizes.

See e.g. AvailableMemory library.

It might be quite hard to exactly calculate and predict the optimizer. However, is it really needed to optimize? Mostly it is best to not optimize before knowing it is really necessary.

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