|
|
View previous topic :: View next topic |
Author |
Message |
esko
Joined: 17 Nov 2016 Posts: 12
|
Pointer to function in a structure |
Posted: Mon Nov 21, 2016 11:35 pm |
|
|
I have a declaration like this:
Code: |
// -----------------------------------------------------------------------
// Callback function pointer
// -----------------------------------------------------------------------
typedef void (*statecb_t)(statecbtype_t aT, stateid_t aSt);
// -----------------------------------------------------------------------
// Structure holding one state item
// -----------------------------------------------------------------------
struct ATTRPACKED state_s {
stateid_t id; // Identification
statecb_t cb; // Callback function. NULL for last
};
typedef struct state_s state_t;
|
In the code this is used like this:
Code: |
void function( void ) {
state_t cbstate;
GetStateArray( &cbstate, Private_State_Stack[Private_State_SP] );
cbstate.cb( statecbtype_init, cbstate.id );
}
|
And finally the compiler gives me this:
*** Error 12 "Private_PostCall.c" Line 42(62,64): Undefined identifier cbstate
This compiles well on MPLAB, avr-gcc, sdcc, cc and g++ but not with ccsc.
There are no preceding errors before that occurs.
I would like to compile this with ccsc |
|
|
esko
Joined: 17 Nov 2016 Posts: 12
|
|
Posted: Tue Nov 22, 2016 12:15 am |
|
|
I got a workaround for this which I assume is a compiler bug.
Code that does not compile: Code: |
// -----------------------------------------------------------------------
// StateRun.c
// -----------------------------------------------------------------------
#include "State_Private.h"
// -----------------------------------------------------------------------
// Call current state with an event
// -----------------------------------------------------------------------
void StateRun ( void ) {
cbstate_t cbstate;
// -------------------------------------------------------------------
// Previous state may have requested operation. Do it now
// -------------------------------------------------------------------
Private_PostCall();
// -------------------------------------------------------------------
// Do a callback
// -------------------------------------------------------------------
GetStateArray( &cbstate, Private_State_Stack[Private_State_SP] );
cbstate.cb( statecbtype_run, cbstate.id );
}
// -----------------------------------------------------------------------
// EOF: StateRun.c
// -----------------------------------------------------------------------
|
Code that compiles Code: |
// -----------------------------------------------------------------------
// StateRun.c
// -----------------------------------------------------------------------
#include "State_Private.h"
// -----------------------------------------------------------------------
// Call current state with an event
// -----------------------------------------------------------------------
void StateRun ( void ) {
cbstate_t cbstate;
statecb_t statecb;
// -------------------------------------------------------------------
// Previous state may have requested operation. Do it now
// -------------------------------------------------------------------
Private_PostCall();
// -------------------------------------------------------------------
// Do a callback
// -------------------------------------------------------------------
GetStateArray( &cbstate, Private_State_Stack[Private_State_SP] );
statecb = cbstate.cb;
statecb( statecbtype_run, cbstate.id );
}
// -----------------------------------------------------------------------
// EOF: StateRun.c
// -----------------------------------------------------------------------
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Tue Nov 22, 2016 4:14 am |
|
|
Your calling syntax doesn't seem right.
To call the function pointed to by cbstate.cb, you would need:
(*cbstate.cb)( statecbtype_run, cbstate.id ); |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Nov 22, 2016 6:03 am |
|
|
Here's an example of the method shown by Ttelmah:
http://www.ccsinfo.com/forum/viewtopic.php?t=53237
This example is somewhat different than your sample
program. The example has an array of structures, each
with a function pointer in it. That's why you'll see it called
as an array element. That's not important. Also there
are no parameters in this example. Again that's not
important. The important thing is how to call the function. |
|
|
esko
Joined: 17 Nov 2016 Posts: 12
|
|
Posted: Tue Nov 22, 2016 7:16 am |
|
|
Did some investigation on this because that code has been working for more than 5 years in a real life production device ... both AVR and PIC devices.
So I changed the code as suggested:
Code: |
(*cbstate.cb)( statecbtype_init, cbstate.id );
|
The compiler then reported:
Code: |
Make /modules/State/pic/CCS
>>> Warning 207 "Private_PostCall.c" Line 42(1,1): Code has no effect
*** Error 76 "Private_PostCall.c" Line 42(73,74): Expect ;
/mnt/xdisk1/Code/Lib/modules/State/pic/CCS/18F25K22/obj/Private_PostCall.o ===> 1 Errors, 1 Warnings.
/mnt/xdisk1/Code/Lib/modules/State/pic/CCS/18F25K22/obj/Private_PostCall.o ===> 1 Errors, 1 Warnings.
|
Then I checked the list file for the code that compiled well:
Code: |
.................... statecb = cbstate.cb;
7716: MOVFF 149,14B
771A: MOVFF 14A,14C
.................... statecb( statecbtype_init, cbstate.id );
771E: MOVFF 148,14D
7722: MOVLW 01
7724: MOVWF FEA
7726: MOVLW 4B
7728: MOVWF FE9
772A: MOVLB 1
772C: CLRF x4E
772E: MOVFF 14D,14F
7732: MOVLB 0
7734: CALL 011C
7738: MOVLB 1
|
At 011C there is following code:
Code: |
011C: MOVFF FEC,FFA
0120: MOVF FED,F
0122: MOVFF FEF,FE8
0126: MOVWF FF9
0128: RETURN 0
|
Despite my rather long career on computing I have no idea whether that code is OK or not. Is it ?
My assumption is that the code is manipulating stack and the actual call happens with the RETURN 0 code.... I would have done it that way
edit: I also tried the wotking approach but made the change in the call:
Code: |
.................... statecb = cbstate.cb;
7716: MOVFF 149,14B
771A: MOVFF 14A,14C
.................... (*statecb)( statecbtype_init, cbstate.id );
771E: MOVFF 148,14D
7722: MOVLW 01
7724: MOVWF FEA
7726: MOVLW 4B
7728: MOVWF FE9
772A: MOVLB 1
772C: CLRF x4E
772E: MOVFF 14D,14F
7732: MOVLB 0
7734: CALL 011C
7738: MOVLB 1
|
The code is exactly the same no matter whether one uses (ptr)(...) or ptr(...). It also compiles with or without the '*'. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Tue Nov 22, 2016 9:23 am |
|
|
No. The jump to the function occurred the line before this.
It takes the number stored in the variable, and writes it directly to the program counter latch registers. On the PIC, this results in a jump as soon as the low byte is written. Basically when you write to the low register, it copies both of these into the actual program counter, and the next instruction will be at the new address. Hopefully the code this jumps to, jumps 'back' to the next address, which then gives the 'return'.
Pushing an address onto the stack is not actually possible on some PIC's at all. So this is not used. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|