Search code examples
cc99generic-programming

Multiple definition of function in the same place


I am trying to simulate generics in C by having some preprocessor definitions for a matrix type. Here is an excerpt of that:

#define __matrix_struct(TYPE) \
  struct { \
    uint32_t sz; \
    TYPE **ptr; \
  }

#define __matrix_t(TYPE) matrix_ ## TYPE
#define __matrix_ptr_t(TYPE) __matrix_t(TYPE) *

#define __matrix_typedef(TYPE) typedef __matrix_struct(TYPE) __matrix_t(TYPE)

#define __matrix_allocator_name(TYPE) TYPE ## _matrix_alloc
#define __matrix_allocator(TYPE) \
  __matrix_ptr_t(TYPE) __matrix_allocator_name(TYPE) (uint32_t sz) { \
    uint32_t i; \
    __matrix_ptr_t(TYPE) m = (__matrix_ptr_t(TYPE)) malloc(sizeof(__matrix_t(TYPE))); \
    m->ptr = (TYPE **) malloc(sz * sizeof(TYPE *)); \
    for (i = 0; i < sz; ++i) { \
      m->ptr[i] = (TYPE *) calloc(sz, sizeof(TYPE)); \
    } \
    return m; \
  }

#define __matrix_deallocator_name(TYPE) TYPE ## _matrix_free
#define __matrix_deallocator(TYPE) \
  void __matrix_deallocator_name(TYPE) (__matrix_ptr_t(TYPE) m) { \
    uint32_t i; \
    for (i = 0; i < m->sz; i++) { \
      free(m->ptr[i]); \
    } \
    free(m->ptr); \
    free(m); \
  }

#define matrix_alloc_ptr(TYPE, SIZE) __matrix_allocator_name(TYPE) (SIZE)
#define matrix_dealloc_ptr(TYPE, PTR_NAME) __matrix_deallocator_name(TYPE) (PTR_NAME)

In another file, byte_matrix.h, I am trying to define a matrix of uint8_t values, as follows:

#include "matrix.h"

typedef uint8_t byte;

__matrix_typedef(byte);

__matrix_allocator(byte)
__matrix_deallocator(byte)

When I try to compile, I get the following errors:

CMakeFiles/tictac.dir/game/board.c.o: In function `byte_matrix_alloc':
/home/victor/dev/pc/tictac/game/../matrix/byte_matrix.h:13: multiple definition of `byte_matrix_alloc'
CMakeFiles/tictac.dir/main.c.o:/home/victor/dev/pc/tictac/game/../matrix/byte_matrix.h:13: first defined here
CMakeFiles/tictac.dir/game/board.c.o: In function `byte_matrix_free':
/home/victor/dev/pc/tictac/game/../matrix/byte_matrix.h:14: multiple definition of `byte_matrix_free'
CMakeFiles/tictac.dir/main.c.o:/home/victor/dev/pc/tictac/game/../matrix/byte_matrix.h:14: first defined here

I cannot understand why it would point to times to the same line and complain about that definition, since every header I wrote has include guards. Could you please explain this to me? Also if you know of a better approach to my problem, please let me know. Thanks.

Also I need to compile with -std=c99 if that matters in this case.


Solution

  • A quick fix would be to add static to your function definitions. This will create a static copy of these functions in each compilation unit which references the header. If you want the functions to be inlined every time, this is the way to go.

    An alternative way to do it would be to keep function declarations in a .h file, and actual definitions in a single .c file. This approach will avoid duplication, and the compiler will not inline them (unless your linker supports link time optimization).

    The reason is that you are including this header file in multiple compilation units. After the preprocessor does all the textual replacements, you end up with actual separate function definitions inside your .c files. And if you don't specify that you want them to be static, they are by default extern, which means that now the compiler doesn't know how to differentiate them if some other part of the code wants to call them.

    This is what you basically do whenever you create a header file: you create a list of declarations which will be included in many compilation units, but there is always a single extern definition in a single .c file.