> Taking Dima's solution in conjunction with the way Apple solved their > similar problem by using opaque types in Cocoa and Carbon: Therefore, if I understand you right, the following C source code example has to be put in a '.h' header file?! struct CW_C_MsgUp_s; typedef struct CW_C_MsgUp_t* CW_C_MsgUp_t; struct CW_C_MsgDown_s; typedef struct CW_C_MsgDown_t* CW_C_MsgDown_t; And the following Dima's struct declaration (completing your example) has to be written in the '.c' source file?! typedef struct CW_C_MsgUp_s { void* ptr; } CW_C_MsgUp_t; typedef struct CW_C_MsgDown_s { void* ptr; } CW_C_MsgDown_t; Is that true? > This will insulate your implementation of those opaque types from the public > header files (note that the structs are forward references, and not declared > publically), and allow you some measure of type safety in C. > > Apple uses a factory function to create their opaque types, and for most > opaque types the CFRelease function to destruct them (using a reference > counting mechanism). That's the role that CW_C_MsgUp_new() and > CW_C_MsgDown_new() provides. Why did you talk about a "reference counting mechanism"? Because in my implementation my C "constructor" and "destructor" functions do not have any counting mechanism, is that a problem. Actually, I rely on the users/callers of the functions to call the "destructor" as many times as the "constructor", avoiding memory losses. But, if you talked about a "reference counting mechanism", is it to prevent memory leaks? By implementing a kind of basic "garbage collector", destroying undeleted allocated structures? Is that what you meant? > As far as them being pointers... I believe that you will want them to be > pointers baked into the typedef. > > The one change to your code would be to change from this... > > CW_C_MsgUp_t *my_up_msg; > CW_C_MsgDown_t *my_down_msg; > > ...to this... > > CW_C_MsgUp_t my_up_msg; > CW_C_MsgDown_t my_down_msg; Yes and no. Because if it will or will not be confused with such a typedef. Because my "*_new" and "*_delete" functions will allocate and destroy objects (structures, classes, int, char buf, etc, who knows, that doesn't matter) and the allocation function on failure can return a null pointer. Therefore how will the caller test the returned value (not considered as pointer because of typedef) with null? I think a workaround could be to pass the "my_up_msg" or "my_down_msg" variables as parameter of "*_new" functions and test an integer returned value of "*_new", telling how everything goes? Example ;o) <example1> typedef struct CW_C_MsgUp_t* CW_C_MsgUp_t; [...] CW_C_MsgUp_t my_up_msg; my_up_msg = CW_C_MsgUp_new(); if (my_up_msg == NULL) /* I think gcc will complain, here! */ { return -1; } [...] </example1> <example2> typedef struct CW_C_MsgUp_t* CW_C_MsgUp_t; [...] int rval = 0; rval = CW_C_MsgUp_new(&my_up_msg); if (rval < 0) { return -1; } [...] </example2> Which of example1 and example2 is better to use? On the same kind of reflexion, how do I have to initialize my_up_msg? 1. my_up_msg = 0; 2. my_up_msg = null; 4. memset(&my_up_msg, 0, sizeof(my_up_msg))? 3. memset(my_up_msg, 0, sizeof(my_up_msg))? The solution I feel is the good one are 2 and 4, but they mean that I do not avoid the fact that "my_up_msg" is a typedef-ed pointer. Solutions 1 and 3 are to be used if the user completely avoids the fact that CW_C_MsgUp_t is a pointer type. How could I do to not confuse the users and me? I'm aware that this solution is very interesting because it does not allow people to dereference the variable. But is that a recommended coding rule? Thanks a lot for all your help. Regards. -- Alex.