Function pointer array, passing values defined in array - c

I'm trying to define an array of function pointers, where each function contains an int parameter. I'm also trying to set the value of that int parameter in the array declaration
So I have a TIMED_TASK struct, that will hold the function pointer and value I want to pass
typedef struct
{
void (*proc)(int);
int delayMsec;
} TIMED_TASK;
Then I have an array of TIMED_TASKs like this
static const TIMED_TASK attractSequence[] =
{
{ LightsOn, 1000 },
{ LightsOff, 500 },
{ EndSequence, 0 }
};
And I'd like it to call each of those functions in turn, passing the delay value to each function. This is where I expect I have the wrong syntax (I'm still learning C). I seemingly don't hit my LightsOn() routine at all
void loop() // It's an arduino project :)
{
attractSequence[sequence];
sequence++;
}
void LightsOn(int pause)
{
// I do not hit this routine for some reason?
Serial.print("LIGHTS ON");
Serial.print(pause);
}
void LightsOff(int pause)
{
Serial.print("LIGHTS OFF");
Serial.print(pause);
}
It's entirely possible I'm taking the wrong approach here, but hopefully you can see what I'm trying to achieve. Any advice very welcome!

If you want to go through each item of attractSequence only once, you can use:
void loop()
{
int count = sizeof(attractSequence)/sizeof(attractSequence[0]);
for (int i = 0; i < count; ++i )
{
attractSequence[i].proc(attractSequence[i].delayMsec);
}
}

Related

How can I use the result from a function as a parameter to another function in C?

In a function that returns void and has no parameters I want to use two other functions (unfortunately I cannot modify that). The first of these functions calculates the result of an int and I want to pass that result as a parameter to the second function. How could I achieve that? thank you.
void descriptionEdit(void)
{
while(1)
{
int fieldno;
if (!pluFields())
{
break;
}
start_editor(setf, esize);
do
{
//code
} while(fieldno>=0);
saveEditor();
}
}
bool pluFields(void)
{
**edplu** = search_productcode();
if (edplu == 0)
{
return true;
}
}
void saveEditor()
{
if (save_plu(**edplu**, &plu))
{
CloseProductIniFile();
cls();
writeat(30, 6, INV2X3, "Save Confirmed");
}
}
So, I want somehow to use the edplu from pluFields function as a parameter to saveEditor function, I thought to make edplu global variable but I think this is a bad practice
You algorithm is very non-intuitive. However, to get a value of a function and pass to another function do this:
int functionName(int param1) {
// calculate values
return variable_here
}
int value = functionName(param1)
then value will go onto the parameter of your next function, like that
void function2(int value) ...
function2(value)
Let me know if I helped.

How to check if a function is calling back to itself

Let's say we have a C function funA in a library, inside funA it'll call some other functions funB, funC, .etc. It's possible that funB and funC could call funA back. So the question is:
Is it possible to detect this situation just inside funA, something like:
void funA(void) {
if (...) {
// Calling back to funA
}
}
Conclusion
In a single thread environment, static/global variable would work.
In multi-thread environment, would have to depend on TLS support.
Haven't got any answer that can achieve this with just language(C) level tricks
This can be done with a static flag.
When the function is called, if the flag is not set then set it and continue, otherwise return right away. Then at the end of the function, you clear the flag so you can enter it again.
void funcA(void)
{
static int callback = 0;
if (callback) return;
callback = 1;
...
callback = 0;
}
If this needs to work in multiple thread separately you can declare the variable as _Thread_local instead of static.
If it is a single call only, you can have a global/static flag set once this function is called, and check it in the beginning. Or to remove the restriction of being single call, you can reset this flag before the function is returning.
Something like that:
void funA(void) {
static bool used = false;
if (used)
{
printf("It is used!\n");
}
used = true;
// .... Do stuff here, including possible recursion
used = false;
}
Note - this won't work with multithreading - this function is not reentrant..
maybe another approach you can identify the caller:
void func_a(void *ptr);
void func_b(void);
void func_c(void);
void func_a(void *caller)
{
if(caller == func_a)
{
printf("called from func_a\n");
return;
}
if(caller == func_b)
{
printf("called from func_b\n");
return;
}
if(caller == func_c)
{
printf("called from func_c\n");
return;
}
if(caller == NULL)
{
printf("called from somewhere elese - going to call myself\n");
func_a(func_a);
}
}
void func_b()
{
func_a(func_b);
}
void func_c()
{
func_a(func_c);
}
int main()
{
func_b();
func_c();
func_a(NULL);
return 0;
}
With a level of indirection, you can even count the number of times your function has been called:
void func( int count )
{
printf( "Count is %d\n", count );
if ( ... ) // no longer want to recurse...
{
return;
}
func( count + 1 );
}
// wrap the actual recursive call to hide the parameter
void funA()
{
func( 0 );
}
This way, it's fully thread-safe. If you don't want a wrapper function nor a parameter passed, you can use thread-specific storage.

C arrays of function pointers

I have three function arrays each pointing to a number of functions.
I can call any of those functions form the three tables.
Now I would like to dereference the three arrays into a single array of function pointers but I just can't get it working!
void afunc1(void);
void afunc2(void);
void afunc3(void);
void bfunc1(void);
void bfunc2(void);
void bfunc3(void);
void cfunc1(void);
void cfunc2(void);
void cfunc3(void);
void(*FuncTbla[])(void) = { afunc1, afunc2, afunc3 };
void(*FuncTblb[])(void) = { bfunc1, bfunc2, bfunc3 };
void(*FuncTblc[])(void) = { cfunc1, cfunc2, cfunc3 };
void (*AllFuncTbls[])(void) = { &FuncTbla, &FuncTblb, &FuncTblc };
int TblNo = 1, FuncNo = 1; // tblNo 1 = table b
bFunc2(); // calls bFunc2 directly
FuncTblb[FuncNo](); // Calls Function bFunc2 via function table b
// Call same function using table of function tables
AllFuncTbls[TblNo][FuncNo](); // Does not compile - expression must be a pointer to a complete object type!!!
Two things: First of all remember that arrays naturally decays to pointers to their first element; And secondly it will become so much easier if you use type-aliases for the function types.
Armed with that knowledge you could do it like e.g.
// Type-alias to simplify using function pointers
typedef void (*function_type)(void);
// The three tables
function_type FuncTbla[] = { &afunc1, &afunc2, &afunc3 };
function_type FuncTblb[] = { &bfunc1, &bfunc2, &bfunc3 };
function_type FuncTblc[] = { &cfunc1, &cfunc2, &cfunc3 };
// A table of pointers to the first elements of each array
function_type *AllFuncTbls[] = { FuncTbla, FuncTblb, FuncTblc };
To call a function using AllFuncTbls is as simple as
AllFuncTbls[TblNo][FuncNo]();
If you use typedefs it works:
void afunc1(void);
// ...
typedef void (*funcPtr)(void);
// void(*FuncTbla[])(void) = { afunc1, afunc2, afunc3 };
// ...
funcPtr FuncTbla[] = { afunc1, afunc2, afunc3 };
funcPtr FuncTblb[] = { bfunc1, bfunc2, bfunc3 };
funcPtr FuncTblc[] = { cfunc1, cfunc2, cfunc3 };
//void (*AllFuncTbls[])(void) = { &FuncTbla, &FuncTblb, &FuncTblc };
funcPtr* AllFuncTbls[] = { FuncTbla, FuncTblb, FuncTblc };
// Use an Array of pointers to function pointers here, not an array of function pointers!
// ...
// Call same function using table of function tables
AllFuncTbls[TblNo][FuncNo](); // Compiles now
I commented out the lines that had to be changed.
Using typealiases is better approach, but if you were courious how to do it without it:
void(**AllFuncTbls[])(void) = { FuncTbla, FuncTblb, FuncTblc};

how to call a sub function only once within an periodically function call

I'm beginner with c and have a simple question:
I have a function myfunction() which is called periodically every 100 ms.
Within this function I have to call an other function but only once at the first call at beginn of myfunction(), but no periodically.
void myfunction() // function is called periodically every 100 ms
{
...
mySubfunction(); // this function have to be called only once in the first call of myFunction() and than skipped each time after that.
} ...
How to realize this in c?
Use static? Something along the lines of
void myfunction() // function is called periodically every 100 ms
{
static int once = 1;
if (once) {
mySubfunction();
once = 0;
}
}
The variable once in the example will be initalized only once and retain its value between invocations because of static keyword.
Be aware of implications in multithreaded environment, see this question.
you can have something like
static int flag = 1
void myfunction() // function is called periodically every 100 ms
{
if(flag)
{
mySubfunction();
flag = 0;
}
}
...
on first look task is very simply, can be next code:
void func()
{
static LONG first = TRUE;
if (_InterlockedExchange(&first, FALSE))
{
subfunc();
}
// some code
}
this give 100% guarantee that subfunc() will be called once and only once even if several thread in concurrent call your func()
but what be if // some code depended on result of subfunc ? in this case task become already not trivial. need some synchronization. and here already depended from os or compiler. in Windows, begin from Vista understand this problem and add function InitOnceExecuteOnce - read Using One-Time Initialization
if your subfunc() have no in and out parameters code can be very simply:
BOOL CALLBACK InitOnceCallback(PINIT_ONCE /*InitOnce*/, PVOID /*Parameter*/,PVOID* /*Context*/)
{
subfunc();
return TRUE;
}
void func()
{
static INIT_ONCE once = RTL_RUN_ONCE_INIT;
if (InitOnceExecuteOnce(&once, InitOnceCallback, 0, 0))
{
// somecode
}
// error init
}
also some modern compilers can correct handle static one time initialization. say latest versions of CL. with it code can be next:
void func()
{
static char tag = (subfunc(), 0);
// some code
}
here CL internally call special functions (implemented in CRT) _Init_thread_header, _Init_thread_footer - implementation can be look in crt source code - thread_safe_statics.cpp
This may be more advanced than you're looking for, but you could use function pointers and change which function gets called.
// Function declarations
void mySubfunction(void);
void myNormalfunction(void);
// Function pointer, which can be changed at run time.
static void (*myfunction)(void) = mySubfunction;
void mySubfunction(void)
{
// Do the sub-function stuff.
// Change the function pointer to the normal function.
myfunction = myNormalfunction();
// Do the normal function stuff (if necessary on the first call).
myNormalfunction();
}
void myNormalfunction(void)
{
// Etc.
}
int main(void)
{
int x;
for(x = 0; x < 3; x++)
{
// Call myfunction as you usually would.
myfunction();
}
return 0;
}

map function pointers to specific numbers at runtime

I have a problem that i can even start to work on because i don't get it how can be done.
So we have a code
int test_handler() {
printf("Test handler called\n");
return 1;
}
// Test your implementation here
int main()
{
register_irq_handler(30, &test_handler);
do_interrupt(29); // no handler registered at this position, should return zero
do_interrupt(30); // calls handler at position 30, expected output: Test handler called
return 0;
}
I need to make those functions register_irq_handler, do_interrupt(29).
But i have no clue how to start, i am looking for a little help to send me on the right direction.
How i store 30 to point to this function when we don't have a global variable to store that "connection" or i am missing something.
You can't do it without a global variable (why would having a global variable be a problem?).
You probably need something like this:
// array of 30 function pointers (all automatically initialized to NULL upon startup)
static int(*functionpointers[30])();
void register_irq_handler(int no, int(*fp)())
{
functionpointers[no] = fp;
}
int do_interrupt(int no)
{
if (functionpointers[no] != NULL)
{
// is registered (!= NULL) call it
return (*functionpointer[no])();
}
else
{
// not registered, just return 0
return 0;
}
}
Disclaimer
This is non tested non error checking code just to give you an idea.

Resources