在C ++项目中,由于C和C ++之间的标准不同,包括C源文件的.h文件会导致许多错误。
如何在C ++项目(或main.cpp)中使用C源文件?
答案 0 :(得分:25)
为获得最大可靠性:
确保C头本身知道C ++,或者C ++代码包含extern "C" { ... }
块内的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 */
或(C ++源代码):
extern "C" {
#include "cheader.h"
}
现代C风格非常接近C和C ++语言的通用子集。但是,由于任何原因,任意C代码都不是C ++代码,只是调用C源文件C ++源文件(通过更改扩展,或者只是通过使用C ++编译器编译)并不能保证成功。通常,将C编译为C和C ++作为C ++更容易,然后将生成的目标文件与C ++编译器链接(以确保调用正确的支持库)。
但是,如果MSVC编译器说使用MFC的程序必须只用C ++编写( MFC需要C ++编译(使用.cpp后缀)是报告的错误),那么你可以别无选择,只能确保您的C代码可以编译为C ++代码。这意味着您必须从malloc()
等投出返回值;你不必担心其他你不使用强制转换将void *
转换为其他指针类型的地方;您必须担心C中的sizeof('a') == 4
和C ++中的sizeof('a') == 1
;你必须确保在使用之前声明每个函数;您必须确保您的C代码不使用任何C ++关键字(特别是typename
,class
;有时也inline
- 但完整列表非常大。)
在某些圈子中,您必须担心在C99中使用C ++ 2003或C ++ 2011中没有的功能,例如灵活的数组成员,指定的初始化程序,复合文字,可变长度数组, 等等。但是,如果C代码用于MSVC,那么这可能不会成为问题; MSVC C编译器不支持这些功能(它只支持C89,而不支持C99)。
FWIW:我有一个脚本来追捕C ++关键字。它包含以下注释:
# 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参考文献的脚注:
(1)
- C ++ 11中的含义已更改答案 1 :(得分:2)
C ++向C源提供“向后兼容性”,因此选项是将C源复制到.cpp文件并构建。 现在C ++ 不完全向后兼容,所以你可能需要在C源代码中改变一些东西,但通常它应该以最小的错误构建。只需确保包含.c使用的C库(考虑到您的编译器也支持C)
#include <stdio.h>
#include <string.h>
//so on
答案 2 :(得分:1)
C ++示例中的最小可运行C
从C ++调用C非常容易:每个C函数只有一个可能的非分解符号,因此不需要额外的工作。
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; }
运行:
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
我已经在What is the effect of extern "C" in C++?
上详细解释了extern "C"
C示例中的最小可运行C ++
从中调用C ++有点困难:我们必须手动创建要公开的每个函数的非混合版本。
这里我们说明了如何向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
答案 3 :(得分:0)
如果您只是使用源代码而不是某些预编译库,在大多数情况下,您只需将.c文件重命名为.cpp文件