Is it possible to cast struct pointer to function pointer in c? - c

From here: ISO C Void * and Function Pointers, I have found a workaround to cast (void*) to function pointer:
int
main(int argc, char *argv[])
{
...
void (*funcp)(void); /* Pointer to function with no arguments */
...
*(void **) (&funcp) = dlsym(libHandle, argv[2]);
}
In other words - to dereference double pointer (another level of indirection).
Now that still assumes, that the final function is of void(*)() type, but I would like to make cast available to other function "types" that can for example accepts some arguments.
Then I found another workaround how to wrap function pointer in struct Why can't I cast a function pointer to (void *)? :
typedef struct
{
void (*ptr)(void);
} Func;
Func vf = { voidfunc };
So I would like to merge these 2 ideas and make possible to pass arbitrary function type as function pointer via struct:
#include <stdio.h>
struct s{
int a, b;
void (*func)();
};
typedef struct{
int (*add)(int,int);
} Func;
int add(int a, int b) { return a+b; }
int main(){
Func f = {add};
struct s foo = {.func=(void*)(&f)};
printf("%i\n",f.add(1,2));
printf("%i\n",foo.func(1,2));
}
Unfortunately, it gives the error:
invalid use of void expression
So the question is, how to cast back the type (void*) to (int*)(int,int) inside of the printf statement?

even if you change the function to return int (int (*func)();) and eventually it will compile, your code is wrong.
Calling the function pointer is in the fact a dereferencing of this pointer.
When you assign the function pointer with the address of the struct, calling this function will actually execute the data inside the struct - not the function referenced struct member. It of course will not be successful.
https://godbolt.org/z/GE464T
The following example is an UB but works on x86 & arm machines and it is only for the illustrational purposes..
struct s{
int a, b;
int (**func)();
};
typedef struct{
int (*add)(int,int);
} Func;
int add(int a, int b) { return a+b; }
int main(){
Func f = {add};
struct s foo = {.func=(void*)(&f)};
printf("%i\n",f.add(1,2));
printf("%i\n",(*foo.func)(1,2));
}
https://godbolt.org/z/rKvGEG
or if you want to use the void (**)() pointer in struct
typedef int func();
struct s{
int a, b;
void (**func)();
};
typedef struct{
int (*add)(int,int);
} Func;
int add(int a, int b) { return a+b; }
int main(){
Func f = {add};
struct s foo = {.func=(void*)(&f)};
printf("%i\n",f.add(1,2));
printf("%i\n",((func *)(*foo.func))(1,2));
}
https://godbolt.org/z/M9qzdf
or
typedef int func();
struct s{
int a, b;
void (*func)();
};
typedef struct{
int (*add)(int,int);
} Func;
int add(int a, int b) { return a+b; }
int main(){
Func f = {add};
struct s foo = {.func=(void*)(&f)};
printf("%i\n",f.add(1,2));
printf("%i\n",(*((func **)foo.func))(1,2));
}
or without typedefs
struct s{
int a, b;
void (*func)();
};
typedef struct{
int (*add)(int,int);
} Func;
int add(int a, int b) { return a+b; }
int main(){
Func f = {add};
struct s foo = {.func=(void*)(&f)};
printf("%i\n",f.add(1,2));
printf("%i\n",(*((int (**)())foo.func))(1,2));
}
https://godbolt.org/z/YG9xd7

Related

Does typedefing a struct re-introduce it every time it is used?

#include <stdio.h>
typedef struct test{
int a;
} my_test;
int main(){
my_test t;
return 0;
}
Is the above code snippet equal to this:
#include <stdio.h>
typedef struct test{
int a;
} my_test;
int main(){
struct test{
int a;
} t;
return 0;
}
(A)
#include <stdio.h>
typedef struct test{
int a;
} my_test;
int main(){
my_test t;
return 0;
}
is equivalent to
(B)
#include <stdio.h>
typedef struct test{
int a;
} my_test;
int main(){
struct test t;
return 0;
}
but it is not equivalent to
(C)
#include <stdio.h>
typedef struct test{
int a;
} my_test;
int main(){
struct test{
int a;
} t;
return 0;
}
(C) Defines a different struct test at block scope within main that overrides the existing definition of struct test with file scope until the end of the block.
In (D)
#include <stdio.h>
struct test{
int a;
};
typedef struct test my_test;
int main(){
struct test{
int a;
} t;
typedef struct test this_test;
this_test u;
my_test s;
return 0;
}
the variables t and u have the same type as each other because struct test and this_test are the same type defined at block scope in main, but s has a different type because my_test is the same type as the struct test defined at file scope.
In (E)
struct {
int a;
} a;
struct {
int a;
} b;
typedef struct {
int a;
} my_type;
my_type c;
my_type d;
the variables a, b and c all have different (anonymous structure) types, but c has the same type as d. For c and d the anonymous structure type used to define the type aliased by my_type has been pinned down by the typedef into something that can be referred to elsewhere.

What does “typedef void *(*Something)(unsigned int)” mean

I am wondering, what does below mean
in .h, it has
typedef void *(*some_name)(unsigned int);
And then in .c
some_name rt;
some_name State= 0;
unsigned int t = 1;
rt = (some_name) State(t);
It creates an alias some_name for a pointer to a function with a return type void* and a single unsigned int parameter. An example:
typedef void *(*my_alloc_type)(unsigned int);
void *my_alloc(unsigned int size)
{
return malloc(size);
}
int main(int argc, char *argv[])
{
my_alloc_type allocator = my_alloc;
void *p = allocator(100);
free(p);
return 0;
}
This typedef
typedef void *(*some_name)(unsigned int);
introduces an alias for pointer to a function of the type void *( unsigned int ) that is that has the return type void * and one parameter of the type unsigned int.
As for this code snippet
some_name rt;
some_name State= 0;
unsigned int t = 1;
rt = (some_name) State(t);
then it does not make a sense.
typedef void *(*some_name)(unsigned int);
^^^^^^^^^
somename is
typedef void *(*some_name)(unsigned int);
^^ ^
a pointer
typedef void *(*some_name)(unsigned int);
^^^^^^^^^^^^^^
to a function that accepts an unsigned int
typedef void *(*some_name)(unsigned int);
^^^^^^
and returns a pointer to void
typedef void *(*some_name)(unsigned int);
^^^^^^^
but for types.
So "the type somename is for functions that accept unsigned and return pointer to void"
#include <stdlib.h>
typedef void *(*some_name)(unsigned int);
void *foo(unsigned t) {
if (t == 0) return NULL;
return malloc(t);
}
int main(void) {
somename fxptr = foo;
void *bar = fxptr(42);
free(bar);
}

C - request for member in something not a structure or union

Long story short I am trying to access a function inside one of my structures. Below is a simplified verson of my code:
#include <stdio.h>
typedef struct
{
void *data;
} A_t;
typedef struct
{
void (*function)(void);
} B_t;
void myfunction(void)
{
fprintf(stdout, "Hello world.\n");
}
int main(int p_argc, char *p_argv[])
{
A_t A;
B_t B;
B.function = myfunction;
A.data = &B;
A.data.function();
return 0;
}
When trying to compile this code I get:
main.c:24:11: error: request for member ‘function’ in something not a structure or union
A.data.function();
Could somebody explain me how to properly access this function via the A-structure?
Thanks
data is of type void *, you need to type cast before de-referencing.
#include <stdio.h>
typedef struct
{
void *data;
} A_t;
typedef struct
{
void (*function)(void);
} B_t;
void myfunction(void)
{
fprintf(stdout, "Hello world.\n");
}
int main(int p_argc, char *p_argv[])
{
A_t A;
B_t B;
B.function = myfunction;
A.data = &B;
((B_t*)(A.data))->function();
return 0;
}

C struct to void* pointer

I have a struct defined as:
typedef struct {
int type;
void* info;
} Data;
and then i have several other structs that i want to assign to the void* using the following function:
Data* insert_data(int t, void* s)
{
Data * d = (Data*)malloc(sizeof(Data));
d->type = t;
d->info = s;
return d;
}
struct {
...
} Struct#;
then i just call
insert_data(1, variable_of_type_Struct#);
When i compile this it gives a warning
warning: assignment from incompatible pointer type
i tried to cast the variable in the insert to (void*) but didn't work
insert_data(1, (void *) variable_of_type_Struct#);
How can i get rid of this warning?
Thanks
Pass in the address of the struct, not a copy of it (i.e. not passed by value):
insert_data(1, &variable_of_type_Struct);
Pass a pointer to the struct object:
struct your_struct_type bla;
insert_data(1, &bla);
Hope this program helps!
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int type;
void* info;
} Data;
typedef struct {
int i;
char a;
float f;
double d;
}info;
Data* insert_data(int t, void* s)
{
Data * d = (Data*)malloc(sizeof(Data));
d->type = t;
d->info = s;
return d;
}
int main()
{
info in;
Data * d;
d = insert_data(10, &in);
return 0;
}
I'm not quite sure what this was:
struct {
...
} Struct#;
So, I cleaned up your program a little bit and got no warnings, after putting the address of the struct into the call, insert_data(1, &variable_of_type_Struct);
#include <stdlib.h>
#include <stdio.h>
typedef struct {
int type;
void* info;
} Data;
Data* insert_data(int t, void* s);
Data variable_of_type_Struct;
Data* insert_data(int t, void* s)
{
Data * d = (Data*)malloc(sizeof(Data));
d->type = t;
d->info = s;
return d;
}
void test()
{
insert_data(1, &variable_of_type_Struct);
}
insert_data waits for a void*, you put a Data.
insert_data(1, &variable_of_type_Struct#);
It miss a level of indirection.

C typedef function prototype with struct attempting to reference before defined.

I need to reference a struct that's not yet defined because the struct actually conatins the typedef'd function prototype.
For example,
typedef int (MyCallbackFunction)(X * x, void * ctx);
typedef struct CallbackData {
MyCallbackFunction * callback;
void * ctx;
} CallbackData;
typedef struct X {
char a;
int b;
int c;
double d;
CallbackData e;
} X;
What's the valid way to actually write this code/header ?
Just forward declare the relevant types - and you can make the function pointer part of the typedef:
struct X_;
typedef int (*MyCallbackFunction)(struct X_ * x, void * ctx);
typedef struct CallbackData_ {
MyCallbackFunction callback;
void * ctx;
} CallbackData;
typedef struct X_ {
char a;
int b;
int c;
double d;
CallbackData e;
} X;
Just forward declare your typedefs
typedef struct X X;
typedef struct CallbackData CallbackData;
and then declare the structs later.
Yes, you can forward declare the struct and use it in the declaration of MyCallbackFunction where you don't need it to be a complete type.
struct X;
typedef int (MyCallbackFunction)(struct X * x, void * ctx);

Resources