Подтвердить что ты не робот

Как использовать исходные файлы C в проекте С++?

В проекте С++, включая файлы .h из исходных файлов C, вы получите много ошибок из-за разных стандартов между C и С++.
Как использовать исходные файлы C в проекте С++ (или в main.cpp)?

4b9b3361

Ответ 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++?

Пример на GitHub.

Минимальная работоспособность 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

Пример на GitHub.