In a C++ project, including .h files of C source files will cause many errors because of different standards between C and C++.
How to use C source files in a C++ project (or in main.cpp)?
You can properly include . C or . CPP files into other source files.
A C file is a source code file for a C or C++ program. It may include an entire program's source code, or may be one of many source files referenced within a programming project. C files can be edited using a basic text editor, but will not show syntax highlighting like most software development programs do.
If the C++ compiler provides its own versions of the C headers, the versions of those headers used by the C compiler must be compatible. Oracle Developer Studio C and C++ compilers use compatible headers, and use the same C runtime library. They are fully compatible.
In the Solution Explorer, right click 'Source Files', choose 'Add' and 'New item' to add a new item. Select 'Visual C++' and 'C++ File(. cpp)'. Change the file extension from .
For the maximum reliability:
Make sure that the C headers are either themselves aware of C++ or that the C++ code includes the C headers inside an extern "C" { ... }
block.
Either (C header file cheader.h
):
#ifndef CHEADER_H_INCLUDED #define CHEADER_H_INCLUDED #ifdef __cplusplus extern "C" { #endif ...main contents of header... #ifdef __cplusplus } #endif #endif /* CHEADER_H_INCLUDED */
or (C++ source code):
extern "C" { #include "cheader.h" }
Modern C style is very close to the common subset of the C and C++ languages. However, arbitrary C code is not C++ code for any of a very large number of reasons, and simply calling the C source files C++ source files (by changing the extension, or simply by compiling with the C++ compiler) is not guaranteed to be successful. In general, it is easier to compile C as C and C++ as C++ and then link the resulting object files with the C++ compiler (to ensure the correct support libraries are invoked).
However, if the MSVC compiler is saying that programs using MFC have to be written solely in C++ (MFC requires C++ compilation (use a .cpp suffix) is the reported error), then you may have no choice but to ensure that your C code is compilable as C++ code. That means you'll have to cast the return values from malloc()
et al; you have to worry about other places where you do not use a cast to convert a void *
into some other pointer type; you have to worry about sizeof('a') == 4
in C and sizeof('a') == 1
in C++; you have to ensure that every function is declared before it is used; you have to ensure your C code does not use any C++ keywords (typename
, class
in particular; also inline
sometimes — but the complete list is quite large).
In some circles, you'd have to worry about the use of features in C99 that are not in C++2003 or C++2011, such as flexible array members, designated initializers, compound literals, variable-length arrays, and so on. However, if the C code is for MSVC, then that probably isn't going to be a problem; those features are not supported by the MSVC C compiler (it only supports C89, not C99).
FWIW: I have a script to hunt down C++ keywords. It contains the following comment:
# http://en.cppreference.com/w/cpp/keywords # plus JL annotations # and C (<iso646.h>) # and_eq C (<iso646.h>) # alignas (C++11 feature) # alignof (C++11 feature) # asm C (core) # auto(1) C (core) # bitand C (<iso646.h>) # bitor C (<iso646.h>) # bool C99 (<stdbool.h>) # break C (core) # case C (core) # catch # char C (core) # char16_t (C++11 feature) # char32_t (C++11 feature) # class # compl C (<iso646.h>) # const C (core) # constexpr (C++11 feature) # const_cast # continue C (core) # decltype (C++11 feature) # default(1) C (core) # delete(1) # double C (core) # dynamic_cast # else C (core) # enum C (core) # explicit # export # extern C (core) # false C99 (<stdbool.h>) # float C (core) # for C (core) # friend # goto C (core) # if C (core) # inline C (core) # int C (core) # long C (core) # mutable # namespace # new # noexcept (C++11 feature) # not C (<iso646.h>) # not_eq C (<iso646.h>) # nullptr (C++11 feature) # operator # or C (<iso646.h>) # or_eq C (<iso646.h>) # private # protected # public # register C (core) # reinterpret_cast # return C (core) # short C (core) # signed C (core) # sizeof C (core) # static C (core) # static_assert (C++11 feature) # static_cast # struct C (core) # switch C (core) # template # this # thread_local (C++11 feature) # throw # true C99 (<stdbool.h>) # try # typedef C (core) # typeid # typename # union C (core) # unsigned C (core) # using(1) # virtual # void C (core) # volatile C (core) # wchar_t C (core) # while C (core) # xor C (<iso646.h>) # xor_eq C (<iso646.h>)
The (1)
suffixes is a footnote at CPP Reference:
(1)
— meaning changed in C++11 Minimal runnable C from C++ example
Calling C from C++ is pretty easy: each C function only has one possible non-mangled symbol, so no extra work is required.
main.cpp
#include <cassert> #include "c.h" int main() { assert(f() == 1); }
c.h
#ifndef C_H #define C_H /* This ifdef allows the header to be used from both C and C++. */ #ifdef __cplusplus extern "C" { #endif int f(); #ifdef __cplusplus } #endif #endif
c.c
#include "c.h" int f() { return 1; }
Run:
g++ -c -o main.o -std=c++98 main.cpp gcc -c -o c.o -std=c89 c.c g++ -o main.out main.o c.o ./main.out
I have explained extern "C"
in more detail at: What is the effect of extern "C" in C++?
Example on GitHub.
Minimal runnable C++ from C example
Calling C++ from is a bit harder: we have to manually create non-mangled versions of each function we want to expose.
Here we illustrate how to expose C++ function overloads to C.
main.c
#include <assert.h> #include "cpp.h" int main(void) { assert(f_int(1) == 2); assert(f_float(1.0) == 3); return 0; }
cpp.h
#ifndef CPP_H #define CPP_H #ifdef __cplusplus // C cannot see these overloaded prototypes, or else it would get confused. int f(int i); int f(float i); extern "C" { #endif int f_int(int i); int f_float(float i); #ifdef __cplusplus } #endif #endif
cpp.cpp
#include "cpp.h" int f(int i) { return i + 1; } int f(float i) { return i + 2; } int f_int(int i) { return f(i); } int f_float(float i) { return f(i); }
Run:
gcc -c -o main.o -std=c89 -Wextra main.c g++ -c -o cpp.o -std=c++98 cpp.cpp g++ -o main.out main.o cpp.o ./main.out
Example on GitHub.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With