-
Organizing C library
Hi Coders,
I have build a library with code i can use in all my projects.
Some structs need types that are not always existing in the main project.
For example some main projects activate the DAC module, when the DAC module is activated the main project have a DAC_HandleTypeDef type.
My idea is to add members to the struct only if the type exist, so In my library's struct i use something like this :
Code:
#ifdef DAC_HandleTypeDef
DAC_HandleTypeDef *pDAC_Speed;
#endif
Problem explination :
i Activate my DAC in the main project, i see that DAC_HandleTypeDef is defined in the mainproject. So far so good.
The problem is that my library code can't see the DAC_HandleTypeDef type, even while the library folders are included in the main project.
I would expect the main project headers are procecced before the libary headers, but that seems not to be the case. So the variable pDAC_Speed is not created as the precompiler thinks DAC_HandleTypeDef is not existing.
How do you guys organise/solve problems like this?
Thank you all
-
The only answer is to rebuild your library with the DAC_HandleTypeDef #define enabled.
Or the library is always built with all the options enabled, and you just have to accept that a few pointers worth of space is wasted.
-
In case the librarary is still source code that you include in every project, is compiled every time new along with your main code, and is then statically linked into your executable, then you'll have the oportunity to define the macro for the current compilation. E.g. in a make file or just in a compiler option (like -D for gcc).
In case the library is already compiled, and dynamically linked at runtime, then it's like Salem already explained.
-
You don't explain what the library is doing. It may be the case that your library doesn't need to see/know about the DAC_Handle, all it needs is to know the size of the containing struct. You might consider passing that in as a parameter, or storing it in an extern size_t global variable, or something. (If all you do is memset(0) the struct for initialization, you don't need to know the individual members, right?)
Or, maybe the library needs to know about the DAC_Handle if it's present, and call some routines, but you can control it with a "flags" mask in the struct: create an enum or some #define bit flags for things like HAS_DAC_HANDLE, and use bitwise-or to combine them into a runtime flags field:
Code:
struct {
bool has_dac :1;
bool has_mmu: 1;
bool has_spqr: 1;
bool init_done: 1;
};
Then you can check for the field(s) at runtime in your library, and call the appropriate functions as needed. This is runtime, not compile-time, so it's less efficient. But if you need to compile your library with everything built in, and then pick and choose features at link time or run time, this is a simple way to make it work.
Or, maybe you change the structure of your include files, so the library #include's the DAC features and "provides" them to the application. So when your main.c file does #include "mylibrary.h" it either gets/doesn't get the DAC features based on a #define you put above it:
Code:
// main.c
#define USE_DAC 1
#include "mylibrary.h"
// struct now includes DAC_Handle