cmoduleceedling

API versus "private" (internal) functions in a C module


When implementing a pure C module which has more than one interface and is split into "submodules", what is the best way to handle internal ("private") interfaces versus API ones? (Obviously C doesn't have private/protected per se, but there are ways to do things.)

Example:

my_module has two interfaces - one towards lower level code (e.g. a HAL) and one towards the app. So in the include folder I have:

my_module_HAL.h
my_module_API.h

and in source folder there are corresponding .c files

Internally, however, functions implemented in my_module_XXX.c need to call each other. What is the best way to do this? I see a few ways, what are the pros and cons of each?

  1. have more .h files in the source folder, called something like _my_module_HAL.h or some other naming convention
  2. use the extern keyword in the source files

Is there any strong reason to choose one over the other? Are there other alternatives that are better? Note that we also want top make unit testing of code as easy and clean as possible, using ceedling.

EDIT:

I chose the first approach, and it works rather well in fact. The code structure is like this:

SRC directory:
 - sub_module_a.c
 - _sub_module_a.h
 _ sub_module_b.c
 - _sub_module_b.h
 - _sub_module_c.c
 - _sub_module_c.h

INC directory:
 - sub_module_a.h
 - sub_module_b.h

In factit is slightly more complex, the publicly available headers in INC are split into parts for the HAL and APP layers, which use the module with entirely different requirements and interfaces. _sub_module.c is an entirely internal function with no public interface (for example, for checking CRCs),

We are using unit testing with the ceedling framework, and this structure seems to work quite well with that. We have good code modularity and you can see from the names of files what they do and where they should be accessed. Quite happy with this solution.


Solution

  • What is the best way to do this? I see a few ways, what are the pros and cons of each?

    have more .h files in the source folder, called something like _my_module_HAL.h or some other naming convention use the extern keyword in the source files

    It appears you are asking whether to use code like this:

    #include "my_module_HAL_internal.h"
    

    or like this:

    extern void foo_internal(…);
    extern void bar_internal(…);
    …
    

    where my_module_HAL_interal.h would contain those extern declarations.

    In this case, the answer is clear: Use the header. This is an instance of DRY: Don’t Repeat Yourself. With the “Write declarations in the source files” method, you have to repeat the declarations in each file that uses them. More repetitions means more possibilities for error, and it also means there is no cross-check between source files.

    When the declarations are written in one header, you can be sure the same declarations are used in each source file, and you only have one set of declarations that needs to be checked for errors. Additionally, when the header is included in the source file(s) that define the identifiers the header declares, the compiler will check the declarations from the headers with the definitions in the source file(s). These are benefits you do not obtain with separately-written declarations.

    When implementing a pure C module which has more than one interface and is split into "submodules", what is the best way to handle internal ("private") interfaces versus API ones?

    This is a broader question, which I will not speak to generally. However, I will point out that linkers or other build tools commonly have features for controlling the visibility of symbols. Typically, you can structure a project: