Moinsen,I am somehow stucked in a design problem. Language is ANSI-C.Lets assume we have a tinkerbox of software-modules:one module for the logic Logic(at least) one module doing some logging Loggertwo modules, both giving a frame to let the program run, lets sayone with a GUIone for commandline...Therefore, the same logic could used in a comandline- and a graphic-version of the software. The Logic has to log some errors but should not know anything about the specific logger as it could be dependent on the frame. It is obvious to give Logic a function pointer that has to be filled by the frame to bind the used Logger to the Logic.At Logging-Module (all code Pseudo-ANSI-C):    void Logger_Log(char *sLogText)    {      //do some stuff    }At Logic-Module:    void Logic_PseudoLog(char *sLogText)    {      printf(sLogText);    }    void(* Logic_Log)(char *sLogText) = &Logic_PseudoLog;    void Logic_SetLogger(void(* LogFct)(char *sLogText))    {      Logic_Log = LogFct;    }At GUI/Cmd-Line:    #include Logger.h    #include Logic.h    Logic_SetLogger(&Logger_Log);Now I want to introduce different severity levels for logging and implement them as an enum in Logger:    //Logger.h:    typedef enum {      DEBUG,      INFO,      ERROR    } teLogLevel;    void Logger-Log(char *sLogText, teLogLevel eLevel);And here the problem rises: The function-pointer at Logic needs to have the correct signature. To do so, it has to know about teLogLevel. Therefore Logic has to know about the Logger, exactly the case I wanted to avoid with the indirection in the first place.    #include Logger.h    void(* Logic_Log)(char *sLogText, teLogLevel eLevel);The situation as layed out is just an example. Please don't solve it by saying something like use int instead of enum or build three functions for the levels. The bottemline question is:How to handle enums in an indirection with functionpointers at ANSI-C?How to inject enums into a module, that should not now about the origin of the enums?
How to handle enums in an indirection with functionpointers at ANSI-C?
design;c;project structure
In your current design, the Logic module already has a dependency on the Logger module, but that dependency is hidden. The dependency lies in the fact that both Logic and Logger must agree on the set of functions used for logging (one function) and their signatures (void (char*)).The way out of here is to clearly separate the interface from the implementation. In particular, the Logger module only provides the logging interface. The implementations are either provided by the GUI/Cmd-Line modules, or by separate Logger-Implementation modules that can depend on the GUI/Cmd-Line modules.The Logger module would only consist of a single header file, like this/* File: Logger.h */typedef enum {  DEBUG,  INFO,  ERROR} teLogLevel;typedef void (*LoggerFuncT)(char *sLogText, teLogLevel eLevel);/* Logger function that discards all logging. Can be used as a safe default. */static void NullLogFunc(char*, teLogLevel) {}All other modules that either use or implement logging functionality need to refer to this header to know the correct function signatures and other types (including enums).For example, the Logic module would use it like this:#include Logger.hLoggerFuncT Logic_Log = NullPseudoLog;void Logic_SetLogger(LoggerFuncT LogFct){  Logic_Log = LogFct;}void Logic_DoSomething(){  Logic_Log(Entering Logic_DoSomething(), DEBUG);  //...  Logic_Log(Leaving Logic_DoSomething(), DEBUG);}In the GUI module, you could have an implementation like this:void GUI_LogToDebugWindow(char* sText, teLogLevel eLevel){    //...}/* Let the Logic module use this function as logger. * The compiler will complain here if the logger signatures don't match. */Logic_SetLogger(GUI_LogToDebugWindow); 