How to define an extern function in multiple files and specify which definition to use?

415 views Asked by At

Not sure if extern is the correct way to handle this situation, but it is what I've currently attempted.

I have a library sharing common code across multiple projects, some of which have different pin configuration that must be done during the _system_pre_init() function in the library (which is called prior to main() due to microprocessor behavior).

Ex:

boot.cpp

extern void Init(void);

// called prior to main() due to microprocessor behavior
extern "C" int _system_pre_init(void)
{
    Init();

    return 1;
}

board1.hpp

void Init(void);

board1.cpp

void Init(void)
{
    // init specific to board 1
}

board2.hpp

void Init(void);

board2.cpp

void Init(void)
{
    // init specific to board 2
}

The plan was for the project implementing the libary to #include whatever board header it needed, which would in turn define the appropriate Init() function.

main.cpp

#include "board1.hpp"

int main(int argc, char ** argv)
{
    //...
}

However, it doesn't look like the board header I include has any effect over the definition of Init(). How can I manage this? Or is there some other paradigm that fits better here?

3

There are 3 answers

2
2785528 On BEST ANSWER

Providing the board headers is an attempt to provide a "compile-time definition" of board hardware instead of a "runtime discovery". I'm hoping this is in someway possible

At most of my embedded system employment this idea was implemented in the make file. i.e. you either build target1 or you build target2. The decision of which you are building is done by the user by selecting the correct target of the make file.

When building the whole system, you would specify 'all'.

With the target identified, the make file only builds the files required by that target.

Conditional compilation flags were not used.

But, perhaps this is not useful ... if you don't use make.

1
sirgeorge On

I can see two options:

  1. Macro - in each header (board1.hpp, board2.hpp) define a macro like this

#define Init Init_boardN

where Init_boardN would be your specific function to init board number N. This allows you to call Init in the old way as Init().

  1. Additional argument to the Init function (suggested enum) to tell it which board to init. You can call the real init function (specific to board) from body of Init based on the argument.
1
Richard Chambers On

It appears that what you are wanting to do is to have a decision at compile time as to what board the application will be using. The function _system_pre_init(void) needs to know which board.

The approach I would consider would be to have a compiler command line define as part of your build environment which would select the target board type. This compiler command line define would then be used in file boot.cpp to include either board1.cpp or board2.cpp, or what ever. Notice that I am saying the board definition C++ source files and not the header files.

The different versions of the boards would all have the same function names, classes, etc. though the implementation would be board specific.

Since the board implementation file would be included into the boot.cpp file it would mean that what ever board file that is included, as determined by the compiler command line option, would be available for the function _system_pre_init(void) as well as the rest of your code.

So for instance you may have a compiler command line option of -DBOARDTYPE=1 or -DBOARDTYPE=2 and then in your boot.cpp file you would have preprocessor macros such as:

#if BOARDTYPE == 1
#include "board1.cpp"
#elif BOARDTYPE == 2
#include "board2.cpp"
#endif

// called prior to main() due to microprocessor behavior
extern "C" int _system_pre_init(void)
{
    Init();

    return 1;
}