How to pass structure to callback function as an argument - c

I am learning C and trying to pass structure to call back function. Gone through online resources but unable to pass structure to call back function. Here is my code.
// myvariables.h
struct callbackStruct
{
int a;
int b;
int c;
};
extern struct callbackStruct callbackStructObject;
typedef void (*callback)(struct callbackStruct);
extern void callback_reg(callback pointerRefCallback);
// Operations.c
struct callbackStruct callbackStructObject;
void callback_reg(callback pointerRefCallback) {
(*pointerRefCallback)(callbackStructObject);
}
// main.c
struct callbackStruct myCallbackStruct1;
void my_callback(struct callbackStruct myCallbackStruct) {
printf("A value:%d" + myCallbackStruct.a);
}
int main()
{
callback ptr_my_callback = my_callback(myCallbackStruct1);
callback_reg(ptr_my_callback);
return 0;
}
Can anyone resolve this scenario?

The type callback is a function pointer type, e.g. a variable of that type is a pointer that points to a function that accepts a struct callbackStruct as single parameter:
typedef void (*callback)(struct callbackStruct);
So when you write (in main):
// ...
callback ptr_my_callback = // HERE
// ...
The expression at HERE must be the address of a function with the correct signature. You write:
my_callback(myCallbackStruct1);
Since my_callback is a function that returns nothing (void) and the above expression calls this function, the expression
callback ptr_my_callback = my_callback(yCallbackStruct1);
is not well formed (syntactically, as well as from the perspective of the type system).
Assuming that my_callback is the function that you want to work as a callback, you need to store its address in the pointer ptr_my_callback:
callback ptr_my_callback = &my_callback;
It's kind of unclear what your code is supposed to achieve, though, so I cannot really help you any further.

Related

C - How to pass _self into a function thats assigned to a pointer

I'm probably getting mixed up as I'm a OO developer. I'm trying to have several instances that call a common method.
I want to somehow reference the caller in a function that is assigned thus...
header
typedef struct _Part Part;
struct _Part {
void (*move)();
}
code
void move(Part p) {
}
void main() {
Part part1;
part1.move = move(part1); <-- Won't compile
part1.move();
}
Is there some way of making this work or do I have to stop thinking like an OO dev and just call the move method directly, passing in the instance?
Declare the structure like
typedef struct _Part Part;
struct _Part {
void (*move)( Part);
};
and just write
part1.move = move;
The function designator is implicitly converted to a pointer to the function.
And then write
part1.move( part1 );

Trying to call function using a void pointer inside a variable type

In the firmware that I am writing, I created a type of variable. Similar to what is below:
struct SitemMenu {
unsigned int id;
char * text;
void * submenu
}
typedef struct SitemMenu TitemMenu;
Be any function:
void functionX () {
...
}
If I create this variable:
TitemMenu itemWhatever;
and do:
itemWhatever.submenu = &function (X);
Can I call functionX doing:
(*itemWhatever.submenu)();
I did something similar to this and the compiler give this answer:
error: (183) function or function pointer required
Yes you can, but not quite the way you've written it.
A function pointer is not declared in quite the same way as a 'normal' pointer.
What you need is:
struct SitemMenu {
unsigned int id;
char * text;
void (* submenu)(void); // this is a function pointer, as opposed to the 'normal' pointer above
};
typedef struct SitemMenu TitemMenu;
TitemMenu itemWhatever;
then, if you have some function declared with the same parameters and return type, like:
void functionX(), then you can do:
itemWhatever.submenu = functionX;
itemWhatever.submenu();

function prototype with void* parameter

I have two functions, each taking a pointer to a different type:
void processA(A *);
void processB(B *);
Is there a function pointer type that would be able to hold a pointer to either function without casting?
I tried to use
typedef void(*processor_t)(void*);
processor_t Ps[] = {processA, processB};
but it didn't work (compiler complains about incompatible pointer initialization).
Edit: Another part of code would iterate through the entries of Ps, without knowing the types. This code would be passing a char* as a parameter. Like this:
Ps[i](data_pointers[j]);
Edit: Thanks everyone. In the end, I will probably use something like this:
void processA(void*);
void processB(void*);
typedef void(*processor_t)(void*);
processor_t Ps[] = {processA, processB};
...
void processA(void *arg)
{
A *data = arg;
...
}
If you typedef void (*processor_t)(); then this will compile in C. This is because an empty argument list leaves the number and types of arguments to a function unspecified, so this typedef just defines a type which is "pointer to function returning void, taking an unspecified number of arguments of unspecified type."
Edit: Incidentally, you don't need the ampersands in front of the function names in the initializer list. In C, a function name in that context decays to a pointer to the function.
It works if you cast them
processor_t Ps[] = {(processor_t)processA, (processor_t)processB};
By the way, if your code is ridden with this type of things and switch's all over the place to figure out which function you need to call, you might want to take a look at object oriented programming. I personally don't like it much (especially C++...), but it does make a good job removing this kind of code with virtual inheritance.
This can be done without casts by using a union:
typedef struct A A;
typedef struct B B;
void processA(A *);
void processB(B *);
typedef union { void (*A)(A *); void (*B)(B *); } U;
U Ps[] = { {.A = processA}, {.B = processB} };
int main(void)
{
Ps[0].A(0); // 0 used for example; normally you would supply a pointer to an A.
Ps[1].B(0); // 0 used for example; normally you would supply a pointer to a B.
return 0;
}
You must call the function using the correct member name; this method only allows you to store one pointer or the other in each array element, not to perform weird function aliasing.
Another alternative is to use proxy functions that do have the type needed when calling with a parameter that is a pointer to char and that call the actual function with its proper type:
typedef struct A A;
typedef struct B B;
void processA(A *);
void processB(B *);
typedef void (*processor_t)();
void processAproxy(char *A) { processA(A); }
void processBproxy(char *B) { processB(B); }
processor_t Ps[] = { processAproxy, processBproxy };
int main(void)
{
char *a = (char *) address of some A object;
char *b = (char *) address of some B object;
Ps[0](a);
Ps[1](b);
return 0;
}
I used char * above since you stated you are using it, but I would generally prefer void *.

C: array of void*

I'm using openCV and need some callback function. these callback function just accept limited parameters. So, if I need more variables for those function, I must make a global variables and turn it around between functions.
For example, here is the callback function :
void mouse_callback(int event, int x, int y, int flags, void* param);
// params : addition parameter, and just one, I need more parameters for this callback.
// but cannot, so make global variable.
And because I shouldn't do that (make global variable), so I decided to make array of (void*) but I afraid C cannot make this, because size of each members can be different.
My question is : can we make array of (void*), and if not, how can I overcome my problem : use callback function and don't need to make global variable.
Thanks :)
Define a struct that is capable of holding all necessary values and pass its address as the param argument:
struct my_type
{
int i;
char c;
};
void my_mouse_callback(int event, int x, int y, int flags, void* param)
{
struct my_type* t = param;
}
Not sure what the registration mechanism is but you need to ensure that the lifetime of the object pointed to by param is valid for the calling period of the callback function:
struct my_type* mouse_param = malloc(sizeof(*mouse_param));
mouse_param->i = 4;
mouse_param->c = 'a';
register_mouse_callback(my_mouse_callback, mouse_param);
Specifically, don't do this:
{
struct my_type mouse_param = { 4, 'a' };
register_mouse_callback(my_mouse_callback, &mouse_param);
} /* 'mouse_param' would be a dangling pointer in the callback. */
You can make array of void * because a pointer has a definite size, however, you cannot use these pointers without casting them.
You need to send a void* that points to a struct with your parameters. In the callback function you cast this type (void*) back to the struct* with your params like this:
typedef struct {
int event;
int x;
int y;
int flags;
} params;
void mouse_callback(void *data) {
params* param = (params*) data;
// now you can use param->x or param->y to access the parameters
}
To pass parameters you need create a paramstruct and cast its address to (void*):
paramstruct myparams;
myparams.x = 2;
myparams.y = 1;
mouse_callback( (void*) &myparams );

Can Someone Explain what this Means? void (*func)();

I have a struct that has a element in it denoted as void (*func)(); I know that void pointers are usually used for function pointers but I cannot seem to define the function. I keep getting dereferencing pointer to incomplete type. I googled around but to no avail. Any advice would be appreciated.
I am trying to do this:
struct callback * cb;
cb->func = *readUserInput;
ReadUserInput is defined as:
void readUserInput(void)
{
}
And Callback is defined as such:
struct callback {
void (*func)();
int pcount;
enum attr_type type;
void *p[0];
};
You need to take the address of the function, not attempt to dereference it.
Change
cb->func = *readUserInput;
to
cb->func = &readUserInput;
Also, you are creating a pointer that has a garbage value and then dereferencing it, causing undefined behaviour. You need to allocate space for it one way or another (malloc/free or just allocate it on the stack):
struct callback cb; // put it on the stack
cb.func = &readUserInput;
or
struct callback * cb = malloc(sizeof(callback));
cb->func = &readUserInput;
...
free(cb);
You have three problems.
Your syntax when assigning the function pointer is incorrect, and you're not actually defining an instance of struct callback.
You want to say:
struct callback cb;
cb.func = readUserInput;
You could explicitly take the address of the readUserInput function, but it is unnecessary. That syntax would look like:
struct callback cb;
cb.func = &readUserInput;
In standard C, a bare function name will be evaluated as the address of the function.
Finally, your callback has the wrong signature. It's defined as a function taking an unknown number of arguments and returning nothing.
Your declaration in the struct calls for a pointer to a function taking no arguments and returning nothing.
Define the callback function as:
void readUserInput()
{
}
or correct the declaration in the struct as:
struct callback {
void (*func)(void);
int pcount;
enum attr_type type;
void *p[0];
};

Resources