Mixing C and C++ in an embedded application
C is the most widely used programming language for embedded applications. For many years, a move to C++ has been anticipated, but its adoption has been quite slow. However, many developers are considering or planning the change. As C++ is, essentially, a superset of C, it is quite possible to mix the two languages …
Although mixing C and C++ is possible, three questions arise:
- why would you do this?
- how do you do it?
- are there any downsides or problems?
Why would you mix C and C++ code in an embedded application?
The short answer is legacy code. It is rare to start a new project from scratch. On that rare occasion, developers may well start out writing everything in C++. However, it is much more likely that reuse of existing code, which may be in-house or from an external source, is the sensible starting point. And that code will be C. So, to move forward using C++, a mixture of languages is almost inevitable.
How can you mix C and C++ code?
There are two basic ways that C and C++ can coexist.
Approach A: The obvious way to mix code is to simply compile each module with its own compiler and then link all the object modules together. However, this causes an immediate problem: link errors will be reported. This is because the C++ compiler changes the names of functions – this is called “mangling”. This change is performed to create unique names that are a combination of the original identifier and the number and types of the function’s parameters. This is done for two reasons. First, it results in link errors if function declarations, definitions and and calls do not correspond. [This is called “typesafe linkage”.] Second, it facilitates function overloading, where two functions have the same name, but take different combinations of parameters; mangling makes each name unique. This problem can be overcome using the extern “C” construct. Declaring a C++ function using this qualifier means that its name is not mangled. Applying it to an external declaration of a C function ensures that the C++ compiler does not mange calls to the function.
Approach B: The alternative is to compile the C code with the C++ compiler – i.e. treat it as if it were C++ code. This would work seamlessly if C were a true subset of C++, but, in fact, some considerable care is needed to “clean up” the code to ensure that it is truly compatible.
Are there any downsides of mixing C and C++ code?
There are very few drawbacks of mixing the languages. Using Approach A there is the issue that type safe linkage is lost, but this is only for C functions called from C++ or vice versa. Other C++ functions are unaffected. Of course, the shared functions cannot be overloaded. Applying Approach B is better in the long term, as the code, once cleaned up, can be treated as C++ and features of the language can be used. However, as mentioned earlier, the cleaning-up process is non-trivial, so the value of the effort must be weighed against the likelihood of future use of the legacy code.
Comments
Leave a Reply
You must be logged in to post a comment.
One benefit in moving C to C++ (Approach B) is that once done the code will be generally safer since C++ is stricter type language.
Nit: spelling mistake in “Declaring a C++ function using this qualifier means that its nam is not mangled”.
Very good point @Ilya.
Nit fixed – thank you.