C: array of void* - c

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 );

Related

How to pass structure to callback function as an argument

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.

Calling a predefined function with void* parameter

I have a function func1 with the signature
int func1(struct a *a1, int b1, const enum c c1);
I want to call this function using another predefined function with the signature
void callerfunc(void (*func)(void *params), void *params);
Note that I cannot modify the above two functions.
To do so, I considered making a new struct pointed to by params which can then be used with a wrapper function to call func1, i.e.
struct param_holder {
struct a a1;
int b1;
enum c c1;
};
int wrapper_func1(void* params) { // params points to initialized struct
return func1(params->a1, params->b1, params->c1);
}
I would like to know if there is a different or better way of achieving this, possibly without creating the wrapper function. Thanks!
Using wrapper is a good solution to me. Just cast before using void pointer :
int wrapper_func1(void* void_params) { // params points to initialized struct
struct param_holder *params = (struct param_holder *) void_params;
return func1(params->a1, params->b1, params->c1);
}

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 *.

How to know the Data type of a variable of unknown type in C?

#include<stdio.h>
void fun(void *x)
{
//what is the data type of 'x', since I could have passed float instead of
// int so first I have to check datatype of this and then proceed further.
}
int main()
{
int n=10;
fun(&n);
}
You can see that we dont know the type of 'x' in function fun() so how could we find out that without using(passing) any other information in function argument?
C11 has type-generic expressions to help you solve this problem. You could do something like this example:
#define myFunction(X) _Generic((X), \
    int *: myFunctionInt, \
    float *: myFunctionFloat, \
    default: myFunctionInt \
    )(X)
void myFunctionInt(int *x);
void myFunctionFloat(float *x);
And then call it the way you are:
int n = 10;
myFunction(&n);
or:
float n = 10.0f;
myFunction(&n);
You will need to implement the separate target functions, but you could just do the pointer magic there and pass off to a common handler, for example.
C does not have runtime type information. When you pass a pointer, then you pass a naked pointer - a memory address.
If you are using pointers to void but need to know the type, then you have to pass some additional information. Otherwise, you create different functions for different types, like foo that expects an int, dfoo that expects a double and so on.
You cannot know the type when you cast to a void *. You have to be careful while using a void pointer, because you can cast it to any type. That is the purpose to have a void pointer.
C does not allow to get the type of the variable passed by void*. The only thing, that you can do it is write kind of object oriented code by your self.
Probably something like this:
typedef struct generic_type_s
{
void* data;
void (*f)(void* data);
} generic_type_t;
void f_int(void* _data)
{
int* data = (int*)_data;
// Do something
}
int main()
{
int data1 = 10;
// Generic variable initialization
generic_type_t gv;
gv.data = &data1;
gv.f = f_int;
// Calling an appropriate function
gv.f(gv.data);
return 0;
}
The C way of doing this is using a tagged union:
typedef enum {
// will default to TypeUnitialized if unspecified in structure initializer
TypeUninitialized = 0,
TypeFloat = 1,
TypeInt
} type_t;
typedef struct {
type_t type;
union {
int u_int;
float u_float;
};
} gen_val_t;
void fun(gen_val_t v)
{
switch (v.type) {
case TypeFloat:
// process float
break;
case TypeInt:
// process int
break;
default:
// error
break;
}
}
int main(int argc, char **argv)
{
gen_val_t ov = { .type = TypeFloat,
.u_float = 3.45 };
fun(ov);
}

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