В проекте С++, включая файлы .h из исходных файлов C, вы получите много ошибок из-за разных стандартов между C и С++.
Как использовать исходные файлы C в проекте С++ (или в main.cpp)?
Как использовать исходные файлы C в проекте С++?
Ответ 1
Для максимальной надежности:
- Скомпилируйте источник C с компилятором C.
- Скомпилировать исходный код С++ с помощью компилятора С++
- Предпочтительно, напишите функцию main() в С++.
- Свяжите программу с компилятором С++.
Убедитесь, что заголовки C либо сами знают С++, либо что код С++ содержит заголовки C внутри блока extern "C" { ... }
.
Либо (файл заголовка C 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 */
или (исходный код на С++):
extern "C" {
#include "cheader.h"
}
Современный стиль C очень близок к общему подмножеству языков C и С++. Тем не менее, произвольный код C не является кодом С++ для любого из очень большого числа причин, и просто вызов исходных файлов C исходных файлов С++ (путем изменения расширения или просто путем компиляции с компилятором С++) не гарантируется, В общем, проще скомпилировать C как C и С++ как С++, а затем связать результирующие объектные файлы с С++-компилятором (чтобы убедиться, что вызваны правильные библиотеки поддержки).
Однако, если компилятор MSVC говорит, что программы, использующие MFC, должны быть записаны исключительно на С++ (MFC требует, чтобы компиляция С++ (с использованием суффикса .cpp) была сообщенной ошибкой), тогда у вас может не быть выбора, кроме как обеспечить, чтобы ваш код C можно компилировать как код на С++. Это означает, что вам нужно будет отображать возвращаемые значения из malloc()
et al; вам нужно беспокоиться о других местах, где вы не используете приведение, чтобы преобразовать void *
в другой тип указателя; вам нужно беспокоиться о sizeof('a') == 4
в C и sizeof('a') == 1
в С++; вы должны обеспечить, чтобы каждая функция была объявлена до ее использования; вы должны убедиться, что ваш C-код не использует ключевые слова С++ (в частности, typename
, class
, а также inline
), но полный список довольно большой).
В некоторых кругах вам придется беспокоиться об использовании функций на C99, которые не находятся в С++ 2003 или С++ 2011, например, о гибких элементах массива, назначенных инициализаторах, сложных литералах, массивах переменной длины, и так далее. Однако, если код C для MSVC, то это, вероятно, не будет проблемой; эти функции не поддерживаются компилятором MSVC C (он поддерживает только C89, а не C99).
FWIW: У меня есть script для поиска ключевых слов на С++. Он содержит следующий комментарий:
# 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>)
Суффиксы (1)
являются сносками в CPP Reference:
-
(1)
- значение изменено в С++ 11
Ответ 2
С++ проповедует "обратную совместимость" с источником C, поэтому опция должна была бы скопировать исходный код C в файл .cpp и построить. Теперь С++ является не ПОЛНОСТЬЮ обратно совместимым, поэтому вам может потребоваться изменить некоторые вещи в источнике C, но в целом он должен строиться с минимальными ошибками. Просто убедитесь, что вы включили библиотеку C, которую использует .c(учитывая, что ваш компилятор также поддерживает C)
#include <stdio.h>
#include <string.h>
//so on
Ответ 3
если вы используете только исходный код, а не некоторые предварительно скомпилированные библиотеки, в большинстве случаев вы можете просто переименовать файл .c в файл .cpp
Ответ 4
Минимальный работоспособный C из примера C++
Вызвать C из C++ довольно просто: каждая функция C имеет только один возможный не искаженный символ, поэтому никакой дополнительной работы не требуется.
main.cpp
#include <cassert>
#include "c.h"
int main() {
assert(f() == 1);
}
ч
#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
куб.см
#include "c.h"
int f() { return 1; }
Бежать:
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
Я объяснил extern "C"
более подробно на: Каков эффект extern "C" в C++?
Минимальная работоспособность C++ из примера C
Вызов C++ from немного сложнее: нам нужно вручную создавать не искаженные версии каждой функции, которую мы хотим представить.
Здесь мы иллюстрируем, как выставить перегрузки функции C++ на 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);
}
Бежать:
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