Search code examples
cstatic-librariesstatic-linkinglibrary-design

How to design the interface for a static library in C


Although I am not an experienced programmer in C, I have to use this language at work to build a static library which compiles both on SunOS and Win32. This library has just a few source files and their correspondent headers (let's say: a.c, b.c, a.h and b.h). The project compiles in both platforms and the library mylib.a is generated.

My problem is how to expose the implemented functions of mylib.a to other projects, because when I add both a.h and b.h I get some macro redefinition errors.

EDIT: I found that the macro redefinition error was because of a macro definition into the compilation command (not related to my headers) and it is solved :) But still I would like advice on organizing my source and header files.

My doubt is whether I modify a.h and b.h to be used externally or if I should create a header file specifically for declaring the interface of this library (let's say mylib.h). I would not like to overcomplicate the original headers, but I would not like to have to keep a different header in sync ... I would like to hear from more experienced C programmers about their patterns, advantages of each approach and whether there are other options.

Thank you in advance.

EDIT: seems I have not provided enough information; the schema below tries to show how my files are organised: each code file only includes its header, each header has a guard condition, each header includes a common header, this common header includes all headers.

// a.c ----
#include "a.h"

// b.c ----
#include "b.h"

// a.h ----
#ifndef GUARD_A_H
#define GUARD_A_H
  # include "liball.h"
  void function_prototypes_implemented_in_a();
#endif // GUARD_A_H

// b.h ----
#ifndef GUARD_B_H
#define GUARD_B_H
  # include "liball.h"
  void function_prototypes_implemented_in_b();
#endif // GUARD_B_H

// liball.h ----
#ifndef GUARD_LIBALL_H
#define GUARD_LIBALL_H
  # include <time.h>   // standard headers
  # include <stdioa.h>

  # include "a.h"      // all headers in this project
  # include "b.h"
#endif // GUARD_LIBALL_H

Solution

  • You should have a public header, mylib.h, that only contains the definitions a user of the library needs to know.

    You then have a private header, mylib-internal.h, that is used within your project. You should not try to keep the two "in sync", but rather have mylib-internal.h contain #include "mylib.h".

    You should also name all your interface functions like mylib_initialize() etc., and ensure that all private, internal functions are either declared static, or else named _mylib_internal_whatever(), so that users don't get namespace clashes with other libraries.