cstructconflicting-librariesname-collision

What is the standard way to fix conflicting types from different libraries in C?


I'm trying to include 3rd party libraries into the .c file but it gives either redefinition or conflicting types error since it has typedef structs with the same name.

I've tried to include guards after reading some answers here in SO and obviously directly changing the typedef on the .h file has solved the problem.

e.g. (Also have to change the functions return type)

// stack.h
typedef struct item stack_item;

// queue.h
typedef struct item queue_item;

However, the original code is as follows:

// stack.h
typedef struct item item;

// queue.h
typedef struct item item;

It throws the following error:

In file included from test.c:5:0:
Queues/queue.c:6:8: error: redefinition of ‘struct item’
 struct item {
        ^

In file included from Stacks/stack.c:4:0, from test.c:4:
Stacks/stack.h:6:16: note: originally defined here
 typedef struct item item;
                ^

I would like to know what is the standard way to solve this, instead of changing the definitions in the .h file


Solution

  • C has only one namespace for structure tags, which also contains the tags of unions and enumerations. You cannot use two different structure types with the same tag in the same scope. There is a different namespace that contains typedefed identifiers, among other things, but again, one type name can mean only one thing in any given scope.

    However, in practice, structure names are significant only at compile time. If you are using packaged, pre-compiled versions of the third-party libraries then probably all you need to worry about is the headers. You might be able to use the preprocessor to change one or both of the tags within the scopes of your program's translation units. For example,

    #define item stack_item
    #include <stack.h>
    #undef item
    
    #define item queue_item
    #include <queue.h>
    #undef item
    

    Your code would then use struct stack_item and / or the typedef stack_item for the one, and struct queue_item and / or queue_item for the other. Be aware that there is a risk of that having a broader effect than you want -- changing structure member names, for example. Additionally, although it has a decent chance to work, it is technically non-conforming to call any functions that have parameters or return types derived from or containing instances of the original structure types (with some caveats).

    In the event that that does not work, you could also consider performing equivalent edits by hand to produce local versions of the headers for use by your project only. This would allow you to be more precise about what gets changed, but using these headers still suffers from the conformance issues described above.

    If you must use both libraries in the same translation unit and you want to ensure that your code conforms to the standard, then you're out of luck. The only conforming alternative is to modify and rebuild one or both libraries so that they no longer have name collisions.