Parameter passing multiple values using void pointer - c

I want to pass multiple arguments to a function using a void pointer.
void* function(void *params)
{
//casting pointers
//doing something
}
int main()
{
int a = 0
int b = 10;
char x = 'S';
void function(???);
return 0;
}
I know that I have to cast them to a certain variable in my function but I do not know how I can pass my 3 arguments as one void pointer to my function.
I have searched for this problem know quite some time but I could not find anything that would help me.

You could do it like this:
struct my_struct
{
int a;
int b;
char x;
}
void * function(void * pv)
{
struct my_strcut * ps = pv; /* Implicitly converting the void-pointer
/* passed in to a pointer to a struct. */
/* Use ps->a, ps->b and ps->x here. */
return ...; /* NULL or any pointer value valid outside this function */
}
Use it like this
int main(void)
{
struct my_struct s = {42, -1, 'A'};
void * pv = function(&s);
}
Following up on the OP's update:
struct my_struct_foo
{
void * pv1;
void * pv2;
}
struct my_struct_bar
{
int a;
int b;
}
void * function(void * pv)
{
struct my_strcut_foo * ps_foo = pv;
struct my_struct_bar * ps_bar = ps_foo->pv1;
/* Use ps_foo->..., ps_bar->... here. */
return ...; /* NULL or any pointer value valid outside this function */
}
Use it like this
int main(void)
{
struct my_struct_bar s_bar = {42, -1};
struct my_struct_foo s_foo = {&s_bar, NULL};
void * pv = function(&s_foo);
}

The void* is used as a pointer to a "generic" type. Hence, you need to create a wrapping type, cast convert to void* to invoke the function, and cast convert back to your type in the function's body.
#include <stdio.h>
struct args { int a, b; char X; };
void function(void *params)
{
struct args *arg = params;
printf("%d\n", arg->b);
}
int main()
{
struct args prm;
prm.a = 0;
prm.b = 10;
prm.X = 'S';
function(&prm);
return 0;
}

Related

C iterate array by known sizeof

I'm trying to make a small library for particle management that allows to "expand" struct with user's data (texture, animation frames, etc). The library would know only the size of the expanded struct.
How do I iterate through the array of unknown struct types but known size of a struct?
typedef struct{
int type;
}Base;
typedef struct{
Base base;
int value;
}inherited;
int main(){
size_t size = sizeof(inherited);
int count = 10;
void *b = malloc(size * count);
for (int i = 0; i < count; i++){
// iterate based on known size & send to callback
callback( &( (size)b )[i] );
}
free(b);
return 0;
}
I assume the code that does the malloc and calls callback doesn't know anything about the type of the object, only its size.
#include <stdlib.h>
void *alloc_and_init(size_t nmemb, size_t size, void (*callback)(void *))
{
void *b = calloc(nmemb, size);
if (b)
{
char *p = b;
for (size_t i = 0; i < nmemb; i++)
{
callback(p);
p += size;
}
}
return b;
}
typedef struct{
int type;
}Base;
typedef struct{
Base base;
int value;
}inherited;
void init_inherited(void *p)
{
inherited *obj = p;
/* do initialization of obj->* here */
}
int main(void)
{
int objcount = 10;
inherited *objarr;
objarr = alloc_and_init(objcount, sizeof(*objarr),
init_inherited);
/* ... */
free(objarr);
}
for( inherited *p = b, *e = p + count; p < e; p++ ){
callback(p);
}
char *b = malloc(size * count);
for (int i = 0; i < count; i++){
// iterate based on known size & send to callback
callback( b + i * size );
}
Polymorphism in C is always rather clunky. Basically you have to construct a "vtable" manually. The naive, simplified version below lets each object have its own function pointer. You'll end up with something rather contrived like this:
#include <stdio.h>
#include <stdlib.h>
typedef struct base_t base_t;
typedef void callback_t (const base_t* arg);
struct base_t
{
int type;
callback_t* callback;
};
typedef struct
{
base_t base;
int value;
} inherited_t;
void callback_base (const base_t* arg)
{
puts(__func__);
}
void callback_inherited (const base_t* arg)
{
const inherited_t* iarg = (const inherited_t*)arg;
printf("%s value: %d\n", __func__, iarg->value);
}
int main (void)
{
// allocate memory
base_t* array [3] =
{
[0] = malloc(sizeof(inherited_t)),
[1] = malloc(sizeof(base_t)),
[2] = malloc(sizeof(inherited_t)),
};
// initialize objects
*(inherited_t*)array[0] = (inherited_t){ .base.callback=callback_inherited, .value = 123 };
*(array[1]) = (base_t){ .callback=callback_base };
*(inherited_t*)array[2] = (inherited_t){ .base.callback=callback_inherited, .value = 456 };
for (int i = 0; i < 3; i++)
{
array[i]->callback(array[i]); // now we get polymorphism here
}
}
A more professional version involves writing a translation unit (.h + .c) per "class" and then combine allocation with initialization in the "constructor". It would be implemented with opaque type, see How to do private encapsulation in C? Inside the constructor, set the vtable corresponding to the type of object allocated.
I'd also boldly claim that any OO solution using void* arguments has some design flaw. The interface should be using the base class pointer. Void pointers are dangerous.

Function pointer pointing to functions with different number of arguments

How to handle assignment of the functions to one function pointer, each with different number of parameters ? The problem is that parameters differ in number and type. If possible give an example.
Function pointers can be cast in the same way as the other pointers. You will have a generic function pointer (similar to void * for storage types), and use it to hold/pass the address of the function. Before calling the function, you will need to cast it to the correct type.
Here is a working example:
#include <stdio.h>
typedef void (*generic_t)(void);
typedef int (*type2_t)(int);
typedef int (*type3_t)(int, char *s);
void test1(void) {
printf("Test 1\n");
}
int test2(int i) {
printf("Test 2 %i\n",i);
return i;
}
int test3(int i, char *s) {
printf("Test 3 %i, %s\n", i, s);
return i++;
}
int main(void) {
generic_t f1, f2, f3;
f1 = &test1;
f2 = (generic_t)&test2;
f3 = (generic_t)&test3;
f1();
int i = ((type2_t)f2)(10);
i = ((type3_t)f3)(20,"This is test");
}
In addition, you will need to implement a mechanism to recognize what is the type of function that the pointer is pointing to. One approach is to use a struct that holds the pointer and the enum of the type.
Another possibility is to create a union of different function pointer types:
union funptr {
void (*v)();
void (*vi)(int);
void (*vs)(char *);
int (*i)();
int (*ii)(int);
int (*iii)(int, int);
int (*is)(char *);
};
You can use void pointers to pass reference to the in and out parameters. Multiple parameters and return values you can wrap in the structs. The return value may return status.
Sometimes it used in low-level device drivers.
typedef int func(void *, void *);
func *fptr;
struct s1
{
int i;
char *s;
};
int test1(void *in, void *out)
{
printf("Test 1\n");
return 0;
}
int test2(void *in, void *out)
{
int *i = in;
printf("Test 2 %i\n", *i);
return *i;
}
int test3(void *in, void *out)
{
struct s1 *s = in;
printf("Test 3 %i, %s\n", s -> i, s -> s);
return ++s -> i;
}
int main(void)
{
fptr = test1;
fptr(NULL, NULL);
fptr = test2;
fptr((int[]){10}, NULL);
fptr = test3;
printf("Returned value: %d\n", fptr(&(struct s1){20,"This is test"}, NULL));
}
You have to declare a new function pointer type for every different signature that you need to handle.

Incompatible type when returning type in C for inner structure

I have a struct that I want to statically allocate at compile time but I'm not sure how to return a pointer to the inner structure.
typedef struct
{
int d;
} innerStruct;
typedef struct
{
int a;
int b;
int c;
innerStruct inner;
} myStruct;
static myStruct m1;
innerStruct * getMyStructPtr()
{
myStruct * ptr = &m1;
return ptr->inner;
}
int main()
{
innerStruct * retval = getMyStructPtr();
return 0;
}
Link to online compiler: https://onlinegdb.com/SJAFJCy0Z
Check the data types!!
Your function promised to return a innerStruct *, whereas your code attempts to returns a innerStruct. They are neither same nor compatible. Fix either and use it appropriately.
Following the function call, it appears that you may want to write
return &(ptr->inner); // return type innerStruct *

how to pass enum value into structure

My problem is I need to pass value from argument (instType, typ1, *op1...) to the structure type tInst.
I'm sure it's a trivial problem but I've spent about 3 hours of my time working on it.
GCC returns segmentation fault 11.
my .h file
typedef enum tInstCode {
I_ADD=0, // (dest, addr, addr) +
I_SUB, // (dest, addr, addr) -
I_MUL, // (dest, addr, addr) *
I_DIV, // (dest, addr, addr) /
} tInstCode;
typedef enum TypeI{
INT=0,
DOUBLE,
STRING
} TypeI;
typedef struct iOperand
{
TypeI type;
void *content;
} iOperand;
typedef struct tInst
{
tInstCode instType;
iOperand *op1;
iOperand *op2;
iOperand *res;
} tInst;
typedef struct ListItem
{
tInst Instruction;
struct ListItem *NextItem;
} tListItem;
my main file :
void generateInstruction(tInstCode instType, TypeI typ1, void *op1, TypeI typ2, void *op2, TypeI typ3, iOperand *op3 )
{
tListOfInstr list;
listInit(&list); //list defined in another file
tInst* I;
I->instType = instType;
I->op1->type = typ1;
I->op1->content = op1;
I->op2 -> type = typ2;
I->op2 -> content = op2;
I->res -> type = typ3;
I->res -> content = op3;
listInsertLast(&list, *I);
}
int main(int argc, char** argv)
{
int a;
a=8;
int *b;
b = &a;
int c;
c=1;
int *d;
d = &c;
generateInstruction(0, DOUBLE, *b, INT, *d, INT, NULL);
}
tInst* I;
I->instType = instType;
You're not allocating memory for I.
As it currently is I is just a pointer with a (potentially) random value. Use malloc to get a suitable address with free memory.
This could be done like this:
tInst* I;
I = malloc(sizeof(tInst));
I->op1 = malloc(sizeof(iOperand));
I->op2 = malloc(sizeof(iOperand));
I->res = malloc(sizeof(iOperand));
Though keep in mind that malloc can fail, so you want to check the return value for NULL.

Equivalent of std::bind in C by hacking the stack

After some research I didn't find a good way to implement the std::bind in C.
I build a small program that implements an equivalent of std::bind in C by hacking the stack.
There's two functions I will try to bind to function with pre-defined arguments.
My problem is this code is only working under Windows. Under Linux, this is a mess. I this the problem is my knowledge of the stack and the way that arguments are store in memory.
Thanks,
Please, find below the code I made:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
The two functions I want to bind :
void test1 (int nombre, char t, int nombre2)
{
printf ("test 1 : %d%c%d\n", nombre, t, nombre2);
}
void test2 (char t, int nombre, int nombre2)
{
printf ("test 2 : %c%d%d\n", t, nombre, nombre2);
}
Two struct that will store the argument of each function (order of fields is important).
typedef struct {
int nombre;
char t;
int nombre2;
} struct1;
typedef struct {
char t;
int nombre;
int nombre2;
} struct2;
This "fake" struct will be use to write on the stack by dereferencing a structvoid* variable.
// Size must be bigger than every struct*
typedef struct {
int i[10];
} structvoid;
The main function.
int main(int argc, char** argv) {
// Variables to store the two functions and their arguments.
void * functions[2];
structvoid * data[2];
void *func1 = (void *)&test1;
void *func2 = (void *)&test2;
void (*functionPtrc)(structurevoid);
// Definition of the argument of the first function test1
struct1 data1;
data1.nombre = 15;
data1.t = 'c';
data1.nombre2 = 30;
// and storing data.
void *datac = malloc (sizeof (structvoid));
memcpy(datac, &data1, sizeof (struct1));
data[0] = (structvoid*)datac;
functions[0] = func1;
// Same thing with function 2.
struct2 data2;
data2.t = 'a';
data2.nombre = 5;
data2.nombre2 = 10;
datac = malloc (sizeof (structvoid));
memcpy(datac, &data2, sizeof (struct2));
data[1] = (structvoid*)datac;
functions[1] = func2;
// Get the pointer to the first function (test1);
functionPtrc = functions[0];
// All the hack is here. By dereferencing the data, this will write on the stack all arguments need by the test1 function.
functionPtrc(*data[0]);
functionPtrc = functions[1];
functionPtrc(*data[1]);
// To check the result.
test1 (data1.nombre, data1.t, data1.nombre2);
test2 (data2.t, data2.nombre, data2.nombre2);
return 0;
}
EDIT
Here a new version of the program by calling function via the calling convention. I only wrote the new lines. The problem of this method is I can only store data inside a "void *" field. If I increase the size of structvoid, I got garbage behaviors.
// Structure that memories each argument
typedef struct {
void *i[1];
} structvoid;
int main(int argc, char** argv) {
// Variables to store the two functions and their arguments.
void * functions[2];
structvoid * data[2];
void *func1 = (void *)&test1;
// Let's start with a maximum of 5 arguments
void (*functionPtrc)(structurevoid, structurevoid, structurevoid, structurevoid, structurevoid);
// Definition of the argument of the first function test1
struct1 data1;
data1.nombre = 15;
data1.t = 'c';
data1.nombre2 = 30;
// and storing data.
structvoid *datac = malloc (sizeof (structvoid)*5);
memcpy(&datac[0], &data1.nombre, sizeof (data1.nombre));
memcpy(&datac[1], &data1.t, sizeof (data1.t));
memcpy(&datac[2], &data1.nombre2, sizeof (data1.nombre2));
data[0] = datac;
functions[0] = func1;
// Get the pointer to the first function (test1);
functionPtrc = functions[0];
// Call the function with the arguments. The unused argument will be ignored.
functionPtrc(data[0][0], data[0][1], data[0][2], data[0][3], data[0][4]);
}

Resources