在C++项目中,由于C和C++之间的标准不同,包括C源文件的.h文件会导致许多错误.
如何在C++项目(或main.cpp)中使用C源文件?
Jon*_*ler 29
为了最大可靠性:
确保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 */
Run Code Online (Sandbox Code Playgroud)
或(C++源代码):
extern "C" {
#include "cheader.h"
}
Run Code Online (Sandbox Code Playgroud)
现代C风格非常接近C和C++语言的通用子集.但是,由于任何原因,任意C代码都不是C++代码,只是调用C源文件C++源文件(通过更改扩展,或者只是通过使用C++编译器编译)并不能保证成功.通常,将C编译为C和C++作为C++更容易,然后将生成的目标文件与C++编译器链接(以确保调用正确的支持库).
但是,如果MSVC编译器说使用MFC的程序必须只用C++编写(MFC需要C++编译(使用.cpp后缀)是报告的错误),那么你可能别无选择,只能确保你的C代码可编译为C++代码.这意味着你必须从malloc()等人那里投出回报值; 您不必担心其他地方不使用强制转换将其转换void *为其他指针类型; 你必须sizeof('a') == 4在C和sizeof('a') == 1C++中担心; 你必须确保在使用之前声明每个函数; 你必须确保你的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>)
Run Code Online (Sandbox Code Playgroud)
该(1)后缀是CPP参考脚注:
(1) - 在C++ 11中改变了意思 来自 C++ 示例的最小可运行 C
从 C++ 调用 C 非常简单:每个 C 函数只有一个可能的非混淆符号,因此不需要额外的工作。
主程序
#include <cassert>
#include "c.h"
int main() {
assert(f() == 1);
}
Run Code Online (Sandbox Code Playgroud)
ch
#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
Run Code Online (Sandbox Code Playgroud)
抄送
#include "c.h"
int f() { return 1; }
Run Code Online (Sandbox Code Playgroud)
跑:
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
Run Code Online (Sandbox Code Playgroud)
我已经extern "C"更详细地解释了:在 C++ 中 extern "C" 的作用是什么?
来自 C 示例的最小可运行 C++
调用 C++ 有点困难:我们必须手动创建我们想要公开的每个函数的非重整版本。
这里我们说明如何向 C 公开 C++ 函数重载。
主文件
#include <assert.h>
#include "cpp.h"
int main(void) {
assert(f_int(1) == 2);
assert(f_float(1.0) == 3);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
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 Code Online (Sandbox Code Playgroud)
跑:
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
Run Code Online (Sandbox Code Playgroud)