菜单
首页/博客/c 与 cpp 混合编译

c 与 cpp 混合编译

为什么不能直接编译

必然不行,问题出现在编译的链接环节。

  1. cpp 中有 c 没有的语法,如类、模板等等

  2. cpp 有名字粉碎(name mangling)机制,和 c 编译器生成符号不同,这会导致链接(link)过程中出现 undefined symbol 等错误

    • 如 void foo(int);,会被 cpp 编译成类似 _Z4fooi 的名字

    • 而 c 语言编译 void foo(int); 后函数名还是 foo

怎么办

用 .hpp 文件定义 cpp 语言,而 .h 需要适配 c,这样可以分开表示

在声明或 .h 中用 extern "C" 来转化所有需要通用的接口。

extern "C" 用法:

  1. 注意这个 "C" 是大写的 C

  2. 单行语句写法:extern "C" void foo(int a);

  3. 多行写法(一般写在 .h 中):

    #ifdef __cplusplus
    extern "C"
    {
    #endif
    
    /* 你的头文件声明代码 */
        
    #ifdef __cplusplus
    }
    #endif
    

如果是你想让 C 语言的 .h 文件能在 C++ 中使用,你需要用在这个头文件中用 extern "C" 把整个代码都括起开,这样 .cpp 文件在 include 这个头文件时就可以把他识别成 C 代码。

如果你想让 C++ 中的一部分代码能用在 C,在这部分代码前同样加 extern "C" 就可以了。但是你无法将 class 等强行变成 C 语言。

extern "C" int Foo(void){
    // 正常的 C++ 代码
}

上面这个函数就可以被 C 语言用了(例如嵌入式用 freertos 时,你想用 C++ 写任务函数,这样就可以用了)

另外,C++ 某个变量或函数要是兼容 C,也要把 extern "C" 写到他的函数实现,他的所有声明也要有,总之一处用处处用,他在所有定义都要用 extern "C"

为什么我给C的头文件也要写 extern"C"?因为include不管你是什么文件,他的原理是复制,详见编译过程的宏处理阶段。

另外 .h 好多 C++ 也在用,所以你并不知道 .h 是谁的头文件。我还是倾向于把 C++ 的头文件写成 .hpp。

vscode

感觉C和C++在一起用时,会有很多奇怪的问题,例如静态语法检查会报错,大概是vsc抽风罢(?)