Pass pointer to EEPROM.get/put

Hi there,

I would like to wrap EEPROM.get and EEPROM.put inside a function and pass/get the data to read/write through a pointer.

I wrote a function

EEPROM_INTERFACE_ReadPage( uint32_ t pageAddress, void* dataBuffer )
{
   EEPROM.get( pageAddress, dataBuffer );
}

Something goes wrong because the dataBuffer is filled woth zeros.

On the other side, how call the EEPROM_INTERFACE_ReadPage, pass the address of the struct that will handle the read data.

Through the castion I can read to EEPROM data structure from different sources.

Is it possible to use a pointer to pass data to EEPROM?

Thanks for the help.

Best regards,
Federico

EEPROM.put() and EEPROM.get() expect a reference in order to understand what datatype they are dealing with. A void* is by definition without data type and hence has lost that information.

However, when you pass an anonymous pointer you usually also need to provide the length of the “structure” that pointer is referring to.

1 Like

Hi @ScruffR,

I forget to add a piace of code.
I can add to the function an enum to specify the structure type and cast the void pointer according to the enum.

My concern is related if EEPROM.get can receive a pointer.

I did a sample test, I tried to pass a point to a struct instead the struct itself but VS Code returns an error

EEPROM.get( 1, &myStruct );

It seems that EEPROM.get cannot receive pointer as argument.

Thanks,
Federico

It seems that EEPROM.get cannot receive pointer as argument.

Correct. Once you’ve taken a pointer to the struct, the EEPROM.get method no longer knows the length of the struct, so you must also pass the length, as ScruffR pointed out. Or pass it by reference, so it can determine the length for you.

1 Like

Pass the struct by reference is what I want to do with &mystruct

EEPROM.get( 1, &myStruct );

But VS Code returns an error.

Thanks

That’s by pointer. By reference is:

EEPROM.get( 1, myStruct );

Adding the & in a C++ method declaration declares a variable that would normally be copied to the stack by reference instead. However adding a & to a function or method call makes it a pointer, not a reference.

With

EEPROM.get( 1, myStruct );

You pass the struct by value.
By reference means passing the address of a variable, so passing the address via a pointer.

References in C++

I want to wrap the EEPROM function inside a high level function, so I need to pass the struct using its address (&struct).

Not quite. You’d need to know how a given function is defined to argue that.
For EEPROM.get() it’s simply not correct.

By reference (in the legacy interpretation) shall not be confused with C++ references.

C++ references need to be declared as T& thisReference but passing a parameter to a function via foo(&someParameter) is not passing a C++ reference.

For a function to take a C++ reference it needs to be declared that way

void foo(T& someParameter);

and called as

  some_t var;
  foo(var);

In the process of passing var (mark the lack of a leading ampersand &) a C++ reference someParameter is created and henceforth will act as if you were directly dealing with var itself (someParameter has become a synonym for var - however, the latter is outside the function’s scope and hence couldn’t be used by foo()).

That’s even illustrated in the swap() sample in the link you provided
image
(no ampersands for a and b)

On the other hand, once your function receives a void* to some entity that parameter will only be a pointer and any C++ reference off that pointer will, in turn, only be a pointer but never again the original entity.

There are ways to do that, but you will not get around the need to actually having a variable off which you can pull a proper C++ reference.

Templating would be one way.
Creating a temporary correctly typed variable by dereferencing the pointer and type casting would be another.

2 Likes

@fedex03:

If you need to pass a pointer to the wrapper, you can just dereference it inside the wrapper.

EEPROM_INTERFACE_ReadPage( uint32_ t pageAddress, <OBJTYPE>* dataBuffer )
{
   EEPROM.get( pageAddress, *dataBuffer );
}

But if your wrapper is doing just that, you might as well do it directly where you call the wrapper and save some stack.

As mentioned before, the way that EEPROM was implemented, you need to have the actual type for the variable, so sizeoff() can get the object’s size.

On a side note, this reference misunderstand comes from the fact that C (not C++) never had a true “pass by reference”, what happens in C is that the caller sends an address (int &foo) as a parameter and the callee receives it as a pointer (int *bar). C++ on the other hand, the caller just passes the object (int foo) and the callee receives it as reference (int &bar). One good implication of this is that there are no null pointers; if you received it by true reference you have a valid object.

1 Like

Exactly, hence this in my post before

Irrespective of whether this temporary variable is the parameter itself or a “real” local variable.

But for the sake of this

which suggests there will be multiple different types of structures to be processed you either want multiple local variables or type casts, or multiple overloads, or a templated function.

1 Like

I was a little bit confused by what you meant with the temp variable, but now I got it!

I would even suggest that you have each of those overloads/templated function to handle the pageAddress on there own, so you can fix any problems in a single place!

Something like

EEPROM_INTERFACE_Read_Data1(Data1 *data)
{
    EEPROM.get(0, *data);
}

EEPROM_INTERFACE_Read_Data2(Data2 *data)
{
    EEPROM.get(0 + sizeof(Data1), *data);
}
1 Like