Sunday, October 27, 2019

How to use C source files in a C++ project?



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)?


Answer




For the maximum reliability:




  • Compile the C source with a C compiler.

  • Compile the C++ source with a C++ compiler

  • Preferably, write the main() function in C++.

  • Link the program with a C++ compiler.



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 ()
# and_eq C ()
# alignas (C++11 feature)
# alignof (C++11 feature)

# asm C (core)
# auto(1) C (core)
# bitand C ()
# bitor C ()
# bool C99 ()
# break C (core)
# case C (core)
# catch
# char C (core)
# char16_t (C++11 feature)

# char32_t (C++11 feature)
# class
# compl C ()
# 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 ()
# 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 ()
# not_eq C ()
# nullptr (C++11 feature)
# operator
# or C ()
# or_eq C ()
# 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 ()
# 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 ()
# xor_eq C ()



The (1) suffixes is a footnote at CPP Reference:




  • (1) — meaning changed in C++11


No comments:

Post a Comment

hard drive - Leaving bad sectors in unformatted partition?

Laptop was acting really weird, and copy and seek times were really slow, so I decided to scan the hard drive surface. I have a couple hundr...