C void pointers in API Design

I am working on a large project that is provided to our customers as a static c lib and one prototype header file for our open API. The project has two similar but unique assemblies that require different data structures to be displayed in the header. I'm trying to come up with a better design to allow one API function to work with different data structures depending on the assembly. This is my idea so far, but I'm worried that this is a bad design.

My function will be implemented as follows

void foo(void *generic_data_struct) { #ifdef BUILD1 build1_t *data_struct = generic_data_struct; #else build2_t *data_struct = generic_data_struct; #endif ... } 

And the open API header will, depending on the assembly of customer orders,

 void foo(build1_t *data_struct); 

or

 void foo(build2_t *data_struct); 

Is this a reasonable design pattern or is it a frown? Thanks!

+4
source share
4 answers

Why not:

 #ifdef BUILD1 foo(build1_t *data_struct) #else foo(build2_t *data_struct) #endif { /* ... */ } 

AFAIK, the standard does not require different types of pointers to be bitwise, so your original idea may not be portable for all possible implementations. That would be if the prototype also used void* (but this, of course, sacrifices some type security in the process).

+3
source

It is almost always better to use an opaque type ( struct foo; ) for that type, rather than void pointers.

Whenever you have build options, it is highly advisable to minimize the number of #ifdefs. I recommend that you use the eq-sentence, but undo the variations in function prototypes with typedef:

 /* header file */ #ifdef BUILD1 typedef build1_t generic_t; #else typedef build2_t generic_t; #endif void foo(generic_t *); void bar(generic_t *); /* etc */ 

You still need #ifdefs inside foo , bar , etc., when the actual behavior changes based on BUILD1 , but you do not need them in the declaration and definition of each individual function.

+5
source
 struct generic_struct { union { struct specific_struct_1 struct_1; struct specific_struct_2 struct_2; }; }; 

This gives you one type that contains both structure definitions in overlapping space.

+1
source

I would advise you not to use compile-time directives to separate functions. Choose at runtime; use if () statements and have a state indication mode.

+1
source

All Articles