C: send different structures for one function argument

I have a function that draws a circle using OpenGL, I would like to give it a structure containing the x and y coordinates and the radius. The problem is that the same function should be used with 3 different structures containing coordinates, radius and some other things that the drawing function does not use.

Is there a way to have only one argument for three different structures (only one is sent at a time).

I hope I was accurate enough.

PS: functions should be "abstract".

+4
source share
2 answers

Yes, you can use a prototype, for example:

void foo(char type, void *data); 

Use this type to tell the function which structure uses the data like, and you are good.

 struct c *prepareStructC(void); //... struct c *toto = prepareStructC(); foo('c', toto); //... void foo(char type, void *data) { int x, y; switch (type) { case 'c': x = ((struct c*)data)->x; y = ((struct c*)data)->y; break; //... } //... } 

The second option, if you want to avoid the / case switch, and after that you can add more structure types without changing foo, you can make sure that all your structures start with the necessary data, always in the same order, with the same type. This way you can do something like an โ€œinterfaceโ€ with C ++ and use abstract versions of the type:

 struct abstract { int x; int y; int radius; } struct a { struct abstract abs; //... other data ... } struct b { struct abstract abs; //... other data ... } struct c { struct abstract abs; //... other data ... } //Two choices : either you have: void foo(void *data) { int x,y,r; x = ((struct abstract*)data)->x; y = ((struct abstract*)data)->y; r = ((struct abstract*)data)->radius; //... } //OR Smarter way: void foo2(struct abstract *data) { int x,y,r; x = data->x; y = data->y; r = data->radius; } //Calling foo2 with: struct a *sa = prepareStructA(); struct b *sb = prepareStructB(); struct c *sc = prepareStructC(); foo2(sa->abs); foo2(sb->abs); foo2(sc->abs); 

The second part of the second method allows you more flexibility by breaking down certain information in a subtype, allows you to place the abs part anywhere in the a / b / c structure and is better in principle. The only purpose for the structure (having coordinates and radius and other things inside the structure is not always the best .)

+3
source

Only if the function takes void* as an argument, and then you attach void* to the correct type of pointer in the function before dereferencing it to access the data inside.

 typedef enum { type1, type2, type3 } datatype; void foo(void* data, datatype type) { switch(type) { case type1: // do something with data by casting it to the proper type break; // ... other cases here } } 

However, by doing this, you must: a) pass another argument indicating that the original type was sent to void* before passing, and b) you are abandoning the type system, which is hardly ever a good idea, and should always be to avoid.

If you follow this approach, it is highly recommended that you create three wrapper functions that take the correct types before calling the function (which accepts void* ) internally. Make this a strict convention to never call the void* function directly; call only the shell. So you still have a type system that helps with compilation errors.

 void bar1(someStruct* data) { foo((void*) data, type1); } void bar2(someOtherStruct* data) { foo((void*) data, type2); } void bar3(yetAnotherStruct* data) { foo((void*) data, type3); } 
+1
source

All Articles