I have been struggling with function pointers for some time now. Maybe you guys can help me out.
In my project I have multiple functionalities for the same device and each functionality is written in its own .c file. The generic functionalities (which apply to all device functions) are written in generic.c.
I would like to create a function pointer array in the generic c file and fill that array in the other function files. So I can call the right function based on a device function identifier in the generic file.
What I have right now:
// in generic.h:
typedef void (*func_ptr_t[])(arguments);
extern func_ptr_t devFunctions[3];
And I would like to:
// in function1.c:
#include "generic.h"
devFunctions[1] = &functionName;
But then it complains about a type specifier missing AND the array initializer must be a list. If I add the type like
func_ptr_t devFunctions[1] = &functionName;
I get an error about an incomplete element type 'func_ptr_t'.
I can't initialize the entire array list from one file since it is filled from multiple files.
Anybody got an idea on how to tackle this?
Thanks!
-edit-
Because you can't use statements outside of functions I've changed my application. Now it does not use an array anymore and it updates the function pointer in the generic.c upon calling the specific function file.
So the end result:
In generic.h:
typedef void (*func_ptr_t)(<function arguments>)
In generic.c:
func_ptr_t devFunction;
In function1.c:
#include "generic.h"
extern func_ptr_t devFunction;
void functionToBeCalledFromMain( void ){
devFunction = functionName;
}
void functionName (void ){
// Function to be called from generic.c via function pointer
}
As most of you pointed out, filling the array is a statement which can't be put outside a function (duh...). So what I wanted is not really going to work in this case. I rewritten my application to update a function pointer (not an array anymore) on every run with the function I need. Saves a lot of trouble :)
Thanks guys!
For an example about functions of the type int f(int);, you can check :
/* function definition */
int functionName(int arg)
{
/* do things */
return arg * 2;
}
/* create the type "function pointer int->int" */
typedef int (*func_ptr_t)(int);
/* create the array */
func_ptr_t devFunctions[3];
int main(void)
{
/* associate the good function */
devFunctions[0] = &functionName;
/* call it with an arg */
return devFunctions[0](42);
}
Putting the above comments together, you probably wanted
typedef void (*func_ptr_t)(arg_type_list);
Related
I am C begginer, I was trying to create a function that modify the content of a struct pointer, but it couldn't make it, instead, the content remains the same.
Here my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int age;
int code;
}person;
void enter(person *struct_pointer);
void main(void)
{
person *person_1 = NULL;
enter(person_1);
printf("CODE: %i\n", person_1->code);
free(person_1);
}
void enter(person *struct_pointer)
{
struct_pointer = malloc(sizeof(*struct_pointer));
struct_pointer->age = 10;
struct_pointer->code = 5090;
}
In the example above when I print code of person_1 it does not print nothing, so I assume is because person_1 is still pointing to NULL.
Can someone pls explain how can I do this, and if it cannot be made why.
Thanks
To change an object (pointers are objects) in a function you need to pass it to the function by reference.
In C passing by reference means passing an object indirectly through a pointer to it. Thus dereferencing the pointer the function has a direct access to the original object.
So your function should be declared and defined the following way
void enter(person **struct_pointer)
{
*struct_pointer = malloc(sizeof(**struct_pointer));
if ( *struct_pointer )
{
( *struct_pointer )->age = 10;
( *struct_pointer )->code = 5090;
}
}
and called like
enter( &person_1 );
Otherwise in case of this function declaration
void enter(person *struct_pointer);
the function will deal with a copy of the value of the passed pointer and changing the copy within the function will not influence on the original pointer.
Pay attention to that according to the C Standard the function main without parameters shall be declared like
int main( void )
You can modify the contents of the struct. It doesn't work for you because you are creating a new struct in the enter function rather than editing the original. Just remove the first line (the one with malloc) and instead allocate the struct in the declaration of the person_1variable.
might be it's silly question but not getting what is wrong in my code.
I am writing simple command parser in which it will initialize appropriate parameters and call appropriate functions related to command code.
Ex.
char buffer[]="1123,13,46";
In above line 1123 is command code and rest of two tokens are parameters. In parser it will first find command code form command table and if command found then it will initialize structure of that command with above parameters.
Currently in my code i am successfully fetching correct command from command table and call that command's functions but failed to initialize the parameters with above values (13 and 46 here).Always getting 0.
As per below code same thing i want in my command parser but little modification
typedef struct
{
void *fields[2];
}tmpStruct;
typedef struct
{
int x;
int y;
}myStruct;
tmpStruct tmp_struct;
myStruct *getParams(tmpStruct *t_struct)
{
myStruct *genericStruct = malloc(sizeof(myStruct));
//setup the order of the fields in the handler
t_struct->fields[0]=(void*)&genericStruct->x;
t_struct->fields[1]=(void*)&genericStruct->y;
return genericStruct;
}
void *fillValue(tmpStruct *t_struct)
{
void *genericStruct;
genericStruct = getParams(t_struct);
*((int*)t_struct->fields[0])=12;
*((int*)t_struct->fields[1])=13;
return genericStruct;
}
void pritValue(myStruct *my_struct)
{
printf("%d %d\n",my_struct->x,my_struct->y);
}
int main()
{
void *genericStruct;
genericStruct = fillValue(&tmp_struct);
pritValue(genericStruct);
return 0;
}
Please find my working source file here
And header file here
The problem is that you are casting function pointers to types of functions that take different parameter types. Trying to make calls to functions through pointers like that is undefined behavior. Although you could potentially get away with calls that are similar - say, return myStruct* in place of void* pointer (although it's still undefined behavior), there is no way you could cast a function that takes an int and a myStruct* to a function type that takes an int and a variable list of arguments.
Changing your functions to the correct signatures to match cmdTableStruct table fixes this problem:
void *setParams(paramHandler_type *pHandler);
int printParams(int commandType,... );
static cmdTableStruct cmdTable[]=
{
{ 1123,setParams,printParams },
//more command in same manner
};
Demo.
Of course now you need to handle parameters from the ... list individually using the functionality from the <stdarg.h> header.
Also, the way you dereference param handler when assigning values is incorrect - the index should be applied to paramValue, not to pHandler:
*((int*)pHandler->paramValue[j]) = (int)atoi(token);
Here I provide the concrete example nevertheless. I have a typedef (from a header file maplec.h defining OpenMaple).
typedef struct {
void (M_DECL *textCallBack) ( void *data, int tag, char *output );
void (M_DECL *errorCallBack) ( void *data, M_INT offset, char *msg );
...
} MCallBackVectorDesc, *MCallBackVector;
In my code I want to assign the callback functions to use. In the examples from the manual (http://www.maplesoft.com/applications/view.aspx?SID=4383&view=html) this is done with
MCallBackVectorDesc cb = { textCallBack,
0, /* errorCallBack not used */
...
};
However I want to keep a reference to this variable cb in a structure which I defined as
struct open_maple {
MCallBackVectorDesc *call_back_vector;
};
Then I initialize with
open_maple->call_back_vector = (MCallBackVectorDesc *)malloc((size_t)sizeof(MCallBackVectorDesc));
(open_maple->call_back_vector)->textCallBack = &textCallBack;
(open_maple->call_back_vector)->errorCallBack = 0;
This code does not produce any compiler warnings nor Segfaults, but I do not seem to receive any calls of textCallBack either, while the online example version would work. I tried other definitions and assignments, but always got warnings or Segfaults.
It boils down to the question: How do I correctly assign the pointers to the callback functions collected in the typedef struct if I do not want to assign them at initialization (in the declaration of the variable cb)?
Edit 1
It has been suggested below that the error occurs because I am referencing the textCallBack function as &textCallBack function which generates a pointer from a pointer. However the example works neither with nor without the &. Note also that the following code works:
/* some standard libraries */
#include <stdlib.h>
#include <stdio.h>
void function(void){
printf("IAMHERE\n");
};
int main()
{
void (*myfunction)(void) = &function;
myfunction();
return 0;
}
I am using gcc -o test test.c to compile it.
Edit 2
Some more investigations showed that the problem is supposedly related to my use of OpenMaple.
textCallBack is defined as a pointer to function.
You're taking the address of it -- pointer to pointer to function.
Is that really what you intend to store into your structure?
Okay so I'm having an issue with a current assignment (trust me this is a minuscule part of it) as we are required to write in C code and not C++, and we are not allowed to change certain parts of code. So I have a struct defined:
typedef struct someStruct {
int what;
int something[MAX];
int another[MAX];
} someType;
in main() I initialize all the values in a defined struct:
someType whatever, *whatptr;
EDIT:of course set the pointer to the struct, trying to simplify the code for the example It is present in my code already
whatptr = &whatever;
whatever.what = 0;
// initialize both arrays to hold 0 at all indexes
// Then I must call a function progRun()
progRun(); //I need to pass struct 'whatever' in some way
Now progRun() looks like this:
void progRun(){
printWhat(&whatever);
if (whatever.what == 0) {
//do stuff
}
}
I can't change anything inside this code except what parameters to pass inside the progRun() function and I can add stuff before printWhat(). I've tried changing progRun to
void progRun(someType *stptr)
then calling it in main as
progRun(whatptr);
but this causes a stack overflow issue for some reason, I've tried stepping through with a debugger and it only occurs when the function is called. Is there a better way to pass the 'whatever' struct to the function so it can be passed into progRun() and printWhat() and can access 'whatever.what'?
Any help would be greatly appreciated! in the meantime I'll try to figure it myself if I can.
EDIT: Something else must be wrong in the code even though everything else has compiled and ran perfectly fine until this code was added. If I can break down the code and find out what's wrong I'll update the question. And no I cannot post the whole code as it is an assignment (this isn't the goal of the assignment trust me it focuses on data forwarding and more, just need to get this basic thing working) Thank you for help everyone.
EDIT: the MAX number used in the struct for something[MAX] and another[MAX] was extremely large ( I left my desktop that I started this project with back home, I'm currently using an old laptop that can't handle large arrays). All the answers below, and some of the stuff I used before now works fine.
void progRun(someStruct *ptr) {
someStruct whatever2 = *ptr;
printWhat(whatever2);
if (whatever2.what == 0) { ...
}
whatptr = &whatever;
progRun(whatptr);
Your problem was that:
you need to pass a pointer to whatever, yet you were passing a variable (whatptr) that had absolutely nothing to do with whatever.
You need to first assign the pointer to whatever into your pointer variable.
You are not dereferencing the pointer in the function
Alternately, get rid of pointer variables:
void progRun(someType *stptr) {
printWhat(*stptr);
if (stptr->what == 0) { ...
}
progRun(&whatever);
Instruction
someType whatever, *whatptr;
is the problem:
*whatptr will not point to the struct whatever unless you do the assignment as follows:
whatptr = &whatever;
Alternatively you could dynamically allocate memory on the heap for a pointer to your struct whatever by using the malloc() function and pass the pointer returned by malloc to the function progrun:
whatptr = (someType*) malloc ( sizeof(someType) );
if (whatptr == NULL) exit (1);
//whatever you need to do with your code
progrun(whatptr); // call function like this
In this case of course you will need to dereference your pointer to access member elements of the struct by using the arrow -> operator:
whatpr->what = 0; // for example
Also, check these tutorials to understand both approaches:
link 1
link 2
If you can't change print and if statements then you should pass your function a copy of your struct:
void progRun( someType whatever ){ // <---Passing by copy
printWhat(&whatever);
if (whatever.what == 0) {
//do stuff
}
}
and in your main() you should just call the function like this:
someType whatever;
//assign values to members of the struct
progRun(whatever);
and do not need at all to define and assign a pointer to the struct.
Though passing variables to functions by copy (especially when they are objects composed by many variables such as a struct is) is not a good behaviour:
it will require an overhead to copy all member elements
your copy will have a limited scope, which means that any change you do to the variable inside of the function will be lost when your function ends and will not be reflected on variable at main scope
Scenario:
There are multiple C structs, each of which contains a function pointer to the same function. These pointers can be different if necessary (pointers to pointers, etc.), but must all point, eventually, to the same function.
Problem:
When the function is called from one of the pointers, I need to retrieve, within the function, which struct it was called from.
e.g.
typedef struct A {
void * (*func)();
... /* Custom properties */
} * A;
typedef struct B {
void * (*func)();
... /* Custom properties */
} * B;
A a_init() {
A a;
... /* Custom initialisation, allocation, etc. */
a->func = myFunc;
return a;
}
B b_init() {
B b;
... /* Custom initialisation, allocation, etc. */
b->func = myFunc;
return b;
}
int main () {
A a = a_init();
void *something = a->func();
}
void * myFunc () {
// Need to get pointer to the instance of the struct this was called from here
}
Is there any way I can retrieve a pointer to the caller within myFunc? If necessary, I was thinking of creating pointers to pointers, etc. to the function, so each instance of an object would have a different pointer, and store all of them in a central location to match them up, but that obviously won't work if I can't even find the instance of the object or the pointer which was used. Any ideas?
Edit:
The question was intended a bit more broadly than I seem to have put it. Currying would be a great solution, if anyone has any ideas as to how to implement it in C. I had some ideas, but I just ended up coming right back to this spot with it.
I don't think there is any way within the language to do that, without explicitly passing some identifier (as an argument or a global) to myFunc. The address of a_init() exists somwhere within the call stack, but it's not accessible from the program.
It's like if somebody showed up at your door unannounced, how would you find out where that person came from without asking?
You can't do that. What you may do, however, is define your structs like this:
typedef struct A {
/* ... */
void *(*func)(void *);
} A;
typedef struct B {
/* ... */
void *(*func)(void *);
} B;
And your function like this:
void *myFunc(void *the_struct) {
/* ... */
}
And call like this:
A a = a_init();
void *something = a->func(a);
Alternatively, if you don't care about portability and for some reason need to be able to call it like a->func(), you may be able to create thunks/trampolines that add in the argument.
Can't be done.
In C++ when you call member functions the compiler implicitly adds this as the first function argument. Mimicking obj->method() syntax in C won't work because there's no implicit this.
This doesn't mean that OO is impossible in C, simply that you can't use the same syntax as C++ or Java do to it. It can still be done, but you have to be explicit:
void * myFunc (void *this) {
...
}
a->func(a);
b->func(b);