由于C和C++编译器对函数名字修饰规则的不同,在有些场景下可能会出现问题,比如:
- C++中调用C语言实现的静态库或者动态库,反之亦然。
- 多人协同开发时,有些人擅长用C语言,有些人擅长使用C++
在这种混合模式下开发,由于C和C++编译器对函数名字的修饰规则不同,可能就会导致链接失败,在该种场景下,就需要使用extern "C" 。
下面我们举一个具体的例子,比如我们在C语言中实现了栈,我们想在C++的环境下使用这个栈,于是我们可以这样做:
一、C++调用C的静态库
1. 修改文件生成方式
2. 生成解决方案后查找静态库的位置
执行:
新建一个cpp的文件,然后根据相对路径包含Stack.h文件
将静态库链接进来
先设置链接库目录
将Debug目录添加到此
然后将静态库添加到附加依赖项中
点击应用后再确定
VS很有可能应用失败,大家要多加检查
最后,因为该库是C语言编译的,所以如果我们要在C++下运行该库,要让C++编译器以C的规则去运行 include 中的内容。
所以我们使用C++专门为此设计的extern ”C“
在包含路径下添加 extern “C”
运行C++文件~
成功!
二、C调用C++的静态库
接下来 我们使用C调用cpp的静态库
首先生成cpp的静态库
在 .c 文件下包含cpp文件的头文件
添加库目录和附加依赖项,这两步和上面C调用C++的步骤是一样的
最后,因为C语言不认识C++编译后的静态库文件,所以我们只能让C++编译器以C的标准去编译这些文件,所以我们再次使用extern "C"包含这些函数
但是!
extern "C" 这条语句C++的编译器才认识,C语言不认识,所以.c文件在使用cpp静态库时,会在#include 处展开,会报出无法识别的字符串的警告,并且影响了后面函数的展开。
使用 #ifdef __cplusplus 预处理语句表示在c++文件中展开,在c文件中不展开,就完美解决了这个问题。
以下面这种形式包含 extern "C".
然后重新生成一下cpp文件中的解决方案
就可以运行啦!!!
这样 C++调用C、C调用C++就可以完美实现了。
三、总结
C++ 调用 C
- 生成 .c 文件对应静态库 .lib ,记录其路径
- 在 cpp 文件中包含将 c语言 的头文件
- 设置附加库和附加依赖项(要反复检查是否添加成功!)
- 在包含路径下添加 extern “C”
C 调用 C++
- 将.cpp文件的函数声明使用extern "C"包含,表示其中的函数使用C的编译方式编译
- 使用预处理指令 #ifdef __cplusplus 表示在C++文件中编译,C语言中不编译
- 生成 .cpp 文件对应的静态库 .lib ,记录其路径
- 在 C语言 文件中包含 C++ 的头文件
- 设置附加库和附加依赖项(要反复检查是否添加成功!)