C和C++混合编程之 extern “C”的使用
C和C++混合编程之 extern “C”的使用
首先要明白:
C++号称是C语言的超集,也确实,从语言的基本语法上,C++是包含所有C语言的语法的,而且C++为了兼容C,连C语言的标准库也被纳入到C++的标准库中,比如在C++中我们仍然可以使用<stdio.h>,它就是C++标准库的一部分(注意最好用新的标准<cstdio>,而不是老的<stdio>)。
但是,C++和C语言的编译器在有些地方还是有差别的。比如,C++是支持面向对象的特性(尽管C++被称为不彻底的面向对象语言),面向对象就要支持函数重载,而函数重载的实现和C++编译器是分不开的。
比如有:
int max(int a, int b);
和
double max(double a,double b);
这两个函数。
这两个函数同时存在,在C语言中是不可以的,因为C语言不支持重载,但是在C++中完全没有问题,因为C++是支持重载的。
那么为什么会这样呢?
这要从编译器的角度来看:
C编译器将int max(int a,int b)函数编译后,在符号库中的名字为_max(不同编译器可能有不同的形式)
C编译器将double max(double a,double b)函数编译后,在符号库中的名字也为_max。所以在C语言中,这两个函数是不能共存的的,编译时会提示错误。
但是C++编译器则不同
C++编译器将int max(int a, int b)编译后,在符号表中的名字为:
_max_int_int
而另一个则为_max_double_double。这两者并不冲突。
这也是C++支持函数重载的根本原因。不过,这也从另一面说明了:函数重载其实不是多态,顶多算是编译时多态。
在C++和C混合编程时:
在C++和C语言混合编程时,前面已经说过,C++的语法是完全包含C语言的语法的,所以不用担心语法上出现什么问题。出现问题的主要原因在编译和链接时。
思考这样一件事情:
我们在Linux下编程的时候,经常会用到内核的库,我们知道Linux内核使用C语言写的。如果这些库采用了C语言的编译器进行编译,而我们的程序是用C++开发的,要用C++进行编译,那么会出现什么问题?
比如:
我们有个.c文件p.c,内容如下:
#include <stdio.h> void print(int a,int b)
{
printf("这里调用的是C语言的函数:%d,%d\n",a,b);
}
我们用gcc –c命令编译它,生成p.o文件
然后我们又p.h文件,里面是print函数的原型声明,如下:
void print(int a,int b);
我们又有main.cpp文件,内容如下
#include <iostream> using namespace std; #include "p.h" int main()
{
cout<<"现在调用C语言函数\n";
print(,);
return ; }
这次我们用g++ -c进行编译,生成main.o文件
然后我们用g++链接两个.o文件,这时我们会发现,报错:

这时为什么呢?
因为:
p.c我们使用的是C语言的编译器gcc进行编译的,其中的函数print编译之后,在符号表中的名字为 _print
而我们链接的时候采用的是g++进行链接,也就是C++链接方式,程序在运行到调用print函数的代码时,会在符号表中寻找_print_int_int(是按照C++的链接方法来寻找的,所以是找_print_int_int而不是找_print)的名字,发现找不到,所以会t提示“未定义的引用”
此时如果我们在对print的声明中加入 extern “C” ,这个时候,g++编译器就会按照C语言的链接方式进行寻找,也就是在符号表中寻找_print,这个时候是可以找到的,是不会报错的。比如我们修改p.h为:
extern "C" void print(int a,int b);
这是结果为:

所以extern “C” 用到函数声明之前,它的作用就是告诉编译器,对于该函数的链接要采用C语言编译器的链接方式,也就是告诉编译器找_fun,而不是_fun_int_int。
如果有多个函数声明都需要在前面加extern “C”,那可以用extern “C”{}的形式。
如果你觉得对你有用,请赞一个吧
C和C++混合编程之 extern “C”的使用的更多相关文章
- C、C++混合编程之extern "C"
为何要“混合编程”?举个例子: CHeader.h #ifndef C_HEADER_H #define C_HEADER_H void func(); #endif CHeader.c #inclu ...
- C++混合编程之idlcpp教程Python篇(9)
上一篇在这 C++混合编程之idlcpp教程Python篇(8) 第一篇在这 C++混合编程之idlcpp教程(一) 与前面的工程相比,工程PythonTutorial7中除了四个文件PythonTu ...
- C++混合编程之idlcpp教程Lua篇(9)
上一篇在这 C++混合编程之idlcpp教程Lua篇(8) 第一篇在这 C++混合编程之idlcpp教程(一) 与前面的工程相比,工程LuaTutorial7中除了四个文件LuaTutorial7.c ...
- C++混合编程之idlcpp教程Python篇(8)
上一篇在这 C++混合编程之idlcpp教程Python篇(7) 第一篇在这 C++混合编程之idlcpp教程(一) 与前面的工程相似,工程PythonTutorial6中,同样加入了四个文件:Pyt ...
- C++混合编程之idlcpp教程Lua篇(8)
上一篇在这 C++混合编程之idlcpp教程Lua篇(7) 第一篇在这 C++混合编程之idlcpp教程(一) 与前面的工程相似,工程LuaTutorial6中,同样加入了四个文件:LuaTutori ...
- C++混合编程之idlcpp教程Python篇(7)
上一篇在这 C++混合编程之idlcpp教程Python篇(6) 第一篇在这 C++混合编程之idlcpp教程(一) 与PythonTutorial4工程相似,工程PythonTutorial5中,同 ...
- C++混合编程之idlcpp教程Lua篇(7)
上一篇在这 C++混合编程之idlcpp教程Lua篇(6) 第一篇在这 C++混合编程之idlcpp教程(一) 与LuaTutorial4工程相似,工程LuaTutorial5中,同样加入了四个文件: ...
- C++混合编程之idlcpp教程Python篇(6)
上一篇在这 C++混合编程之idlcpp教程Python篇(5) 第一篇在这 C++混合编程之idlcpp教程(一) 工程PythonTutorial4中加入了四个文件:PythonTutorial4 ...
- C++混合编程之idlcpp教程Lua篇(6)
上一篇在这 C++混合编程之idlcpp教程Lua篇(5) 第一篇在这 C++混合编程之idlcpp教程(一) 工程LuaTutorial4中加入了四个文件:LuaTutorial4.cpp, Tut ...
随机推荐
- eclipse中tomcat 中server location灰色,如何修改?
Eclipse中tomcat service设置选择window ----show view---services可以看到服务的面板双击tomcat进入配置界面Service Locations(Sp ...
- Node.js 入门:Express + Mongoose 基础使用
前言 Express 是基于 Node.js 平台的 web 应用开发框架,在学习了 Node.js 的基础知识后,可以使用 Express 框架来搭建一个 web 应用,实现对数据库的增删查改. 数 ...
- 仿PC版微信的练手项目(可实时通讯)
仿PC版微信的DEMO 本项目是由一个仿PC版微信的vue前端项目,和一个使用leancloud进行数据存储的.提供WebSocket的node后端项目构成. 本项目使用的技术栈:vue + vue- ...
- 4G内存服务器的MySQL配置优化
公司网站访问量越来越大(日均超10万PV),MySQL自然成为瓶颈,关于 MySQL 的优化,最基本的是 MySQL 系统参数的优化. MySQL对于web架构性能的影响最大,也是关键的核心部分.My ...
- T-SQL笔记总结(1)
--1.创建一个数据库 createdatabase School; --删除数据库 dropdatabase School; --创建一个数据库的时候,指定一些数据库的相关参数,比如大小,增长方式, ...
- 一篇关于Python装饰器的博文
这是一篇关于python装饰器的博文 在学习python的过程中处处受阻,之前的学习中Python的装饰器学习了好几遍也没能真正的弄懂.这一次抓住视频猛啃了一波,就连python大佬讲解装饰器起来也需 ...
- ASP.NET程序运行出现WebDev.WebServer40.exe已停止工作解决方法(netsh winsock reset)
问题描述:在开发系统时候运行程序突然报出"WebDev.WebServer40.exe已停止工作"的错误,程序调试运行,发现程序在打开数据库时候报错,也就是Connection.O ...
- vuex状态管理,state,getters,mutations,actons的简单使用(一)
之前的文章中讲过,组件之间的通讯我们可以用$children.$parent.$refs.props.data... 但问题来了,假如项目特别大,组件之间的通讯可能会变得十分复杂... 这个时候了我们 ...
- LinkQueue(链队列)
关于Node.h,请参考LinkStack #include"Node.h" template<typename ElemType> class LinkQueue { ...
- Mybatis源码分析-BaseExecutor
根据前文Mybatis源码分析-SqlSessionTemplate的简单分析,对于SqlSession的CURD操作都需要经过Executor接口的update/query方法,本文将分析下Base ...