[C] A Catch-22 situation with function pointer? - Page 1
Forum section: electronics / general

author: poorchava
author_rank: Super Contributor
timestamp: July 03, 2014, 10:23:05 pm
content: So i wrote a code like thisCode:typedef struct MenuState_t{/**Pointer to function that will handle button presses for the state*/void (*ActionHandler)(MenuState_t *pState, Direction_t dir);/**Pointer to function that will take underlying system variable*and convert it to what should be displayed on lower line of lcd*/void (*DisplayVariable)(MenuState_t *pState);};The way I intend to use it is something like thisCode:MenuState_t Currentstate;CurrentState.ActionHandler(&CurrentState, RIGHT)But I'm getting following errors:Code: C:\CooCox\CoIDE\workspace\MPPT\inc/mppt_types.h:67:24: error: unknown type name 'MenuState_t' void (*ActionHandler)(MenuState_t *pState, Direction_t dir); ^ C:\CooCox\CoIDE\workspace\MPPT\inc/mppt_types.h:67:45: error: unknown type name 'Direction_t' void (*ActionHandler)(MenuState_t *pState, Direction_t dir); C:\CooCox\CoIDE\workspace\MPPT\inc/mppt_types.h:72:26: error: unknown type name 'MenuState_t' ^ void (*DisplayVariable)(MenuState_t *pState); ^ C:\CooCox\CoIDE\workspace\MPPT\inc/mppt_types.h:82:1: warning: useless storage class specifier in empty declaration [enabled by default] };Any idea what am I doing wrong? The only way I can think of, is that I am using pointer to MenuState_t while this type ius actually being defined, but I don;t know how to work around that. Any ideas?

author: zapta
author_rank: Super Contributor
timestamp: July 03, 2014, 10:52:27 pm
content: I think you are missing the new type name before the ';' of the typedef statement. Check the syntax of typedef.

author: rob77
author_rank: Super Contributor
timestamp: July 03, 2014, 10:58:16 pm
content: +1probably you meant to have a struct MenuState and then a type defined as MenuState_t ?

author: Galaxyrise
author_rank: Frequent Contributor
timestamp: July 03, 2014, 11:02:29 pm
content: In typedefs, the syntax isCode:typedef type name;so to typedef a struct, you could do something likeCode:typdef struct{int x,y;} Point;But what if you want to reference the struct from inside the struct? Then there's another, optional name you can give it for use inside the struct definition:Code:typedef struct tagMenuState{void (*func)(tagMenuState *);} MenuState_t;You could see if your compiler supports C++ struct declaration syntax (a lot of modern C compilers allow certain C++ syntactical sugar, like // comments):Code:struct MenuState_t{void (*func)(MenuState_t *);};It's like what you started with, but without the typedef keyword.

author: poorchava
author_rank: Super Contributor
timestamp: July 03, 2014, 11:04:55 pm
content: That's a bad paste. What ended up working, is thisCode:typedef struct MenuStateStruct {/**Pointer to function that will handle button presses for the state*/void (*ActionHandler)(struct MenuStateStruct *pState, Direction_t dir);/**Pointer to function that will take underlying system variable*and convert it to what should be displayed on lower line of lcd*/void (*DisplayVariable)(struct MenuStateStruct *pState);} MenuState_t;So i just declare *pState argument not as pointer to variable of type MenuState_t, but rather to structure of type MenuStateStruct. I think it actually means the same, right?Before, I generally assumed, that when I use a pointer to a type, that type does not have to be declared completly, since pointer to it will always be an uint 32 anyway (or whatever the addressing length would be on the particular machine).

author: zapta
author_rank: Super Contributor
timestamp: July 03, 2014, 11:20:56 pm
content: What compiler are you using? With C++ (e.g. avr-gcc) you don't need the 'typedef' part and can use the class syntax for structs as well.struct MyStruct {...};and then just use 'MyStruct' as a type name.

author: dannyf
author_rank: Super Contributor
timestamp: July 04, 2014, 01:11:07 am
content: My 2 cents:1) the struct definitions here make no practical sense: I cannot see a way for you to actually use them.2) having said that, packaging functions (via function pointers) and data into a struct is the new way of doing things in C -> it is effectively a C++ approach to embedded C programming: more structured but without C++'s overhead.For a good example, take a look at how RTE was done in Keil 5.0. Fabulously implemented.Over the last couple years, I have been migrating my code base to this approach, however slowly.

author: andyturk
author_rank: Frequent Contributor
timestamp: July 04, 2014, 01:27:16 am
content: Quote from: dannyf on July 04, 2014, 01:11:07 amWhat overhead are you referring to?

author: IanB
author_rank: Super Contributor
timestamp: July 04, 2014, 01:31:21 am
content: Quote from: poorchava on July 03, 2014, 10:23:05 pmI can't quite get my head round what you are trying to do there, but in C (and C++) if you want to reference something before you have fully defined it you can use a forward pointer definition. You can't reference the thing itself, but you can reference a pointer to the thing since the compiler doesn't need to know the internal structure of the thing to allocate a pointer to it.For instance you can declare:Code:struct Foo;without saying what Foo contains. This allows you to define a pointer as:Code:struct Foo *p;and this will be a usable pointer to objects of type struct Foo, even though you haven't told the compiler what Foo really is yet. As long as the compiler knows what struct Foo really is before you try to de-reference p then everything will be OK.

author: zapta
author_rank: Super Contributor
timestamp: July 04, 2014, 01:53:25 am
content: Quote from: dannyf on July 04, 2014, 01:11:07 amI saw this pattern in device drivers long time ago. The down side is that you duplicate the pointers in each instance instead of a common per class table.If you have access to a good c++ compiler give it a try and see what overhead you get for virtual methods. The compiler has room for optimizations.

author: poorchava
author_rank: Super Contributor
timestamp: July 04, 2014, 05:14:10 am
content: I'm using CooCox, and so the compiler is gcc.What I'm trying to do is to implement a user configuration menu with a character LCD and 4 buttons. The problem is that there is about 80 parameters to set, but so in the thought that I will do a sort of pointer based list of states.

author: dannyf
author_rank: Super Contributor
timestamp: July 04, 2014, 06:56:40 am
content: You can pass the parameters as a pointer to a struct, or a struct of structs if some of the parameters can be grouped, to a function pointer so they can be processed.A struct that contains a function pointer that points to just a struct of the same function pointer would do nothing for you.

author: zapta
author_rank: Super Contributor
timestamp: July 04, 2014, 07:06:33 am
content: Quote from: poorchava on July 04, 2014, 05:14:10 amIf your compiler supports C++ then no need to reinvent your own virtual methods, let the language handle it. Define a base class with virtual methods of the common operations (handle button, display etc), implement a sub class for each of your state, instantiate one instance of each of the sub classes and you have everything you need.The state subclasses can have variables specific for each state, as needed.

author: Mechatrommer
author_rank: Super Contributor
timestamp: July 04, 2014, 02:51:25 pm
content: ditto, polymorphism in its purest form. its not common nowadays to see people try to do it such way but anyway i give itperharp you can get rid of unneccesary hence wasted spaces in the virtual table.