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(3,4);
  return 0;

}

这次我们用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”{}的形式。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • C++ 中CListCtrl的每个项都显示不同的提示信息

    C++ 中CListCtrl的每个项都显示不同的提示信息 添加CToolTipCtrl成员变量m_toolTipCtrl,CListCtrl成员变量m_ListUser,CImageList成员变量m_imageList(这个可以不要) 在OnInitDialog()函数里加下面代码 m_BoradcastEnd.EnableWindow(FALSE); m_imageList.Create(32, 32, ILC_COLOR8, 2, 2); DWORD dwStyle = m_ListUse

  • 基于C++的农夫过河问题算法设计与实现方法

    本文实例讲述了基于C++的农夫过河问题算法设计与实现方法.分享给大家供大家参考,具体如下: 问题描述: 一个农夫带着-只狼.一只羊和-棵白菜,身处河的南岸.他要把这些东西全部运到北岸.他面前只有一条小船,船只能容下他和-件物品,另外只有农夫才能撑船.如果农夫在场,则狼不能吃羊,羊不能吃白菜,否则狼会吃羊,羊会吃白菜,所以农夫不能留下羊和白菜自己离开,也不能留下狼和羊自己离开,而狼不吃白菜.请求出农夫将所有的东西运过河的方案. 实现上述求解的搜索过程可以采用两种不同的策略:一种广度优先搜索,另一种

  • C++ 中随机函数random函数的使用方法

    C++ 中随机函数random函数的使用方法 一.random函数不是ANSI C标准,不能在gcc,vc等编译器下编译通过. 可改用C++下的rand函数来实现. 1.C++标准函数库提供一随机数生成器rand,返回0-RAND_MAX之间均匀分布的伪随机整数. RAND_MAX必须至少为32767.rand()函数不接受参数,默认以1为种子(即起始值). 随机数生成器总是以相同的种子开始,所以形成的伪随机数列也相同,失去了随机意义.(但这样便于程序调试) 2.C++中另一函数srand(),

  • C++中继承与多态的基础虚函数类详解

    前言 本文主要给大家介绍了关于C++中继承与多态的基础虚函数类的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 虚函数类 继承中我们经常提到虚拟继承,现在我们来探究这种的虚函数,虚函数类的成员函数前面加virtual关键字,则这个成员函数称为虚函数,不要小看这个虚函数,他可以解决继承中许多棘手的问题,而对于多态那他更重要了,没有它就没有多态,所以这个知识点非常重要,以及后面介绍的虚函数表都极其重要,一定要认真的理解~ 现在开始概念虚函数就又引出一个概念,那就是重写(覆

  • C/C++实现控制台输出不同颜色字体的方法

    本文实例讲述了C/C++实现控制台输出不同颜色字体的方法.分享给大家供大家参考,具体如下: 在控制台输出不同颜色的字 效果 代码: #include "stdio.h" #include "windows.h" int main(int argn, char **argv) { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_GREEN); printf("Hello&q

  • C++中BitBlt的使用方法详解

    BitBlt 该函数对指定的源设备环境区域中的像素进行位块(bit_block)转换,以传送到目标设备环境. 原型: BOOL BitBlt( HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HDC hdcSrc, int nXSrc, int nYSrc, DWORD dwRop): 参数: hdcDest:指向目标设备环境的句柄. nXDest.nYDest:指定目标矩形区域左上角的X轴和Y轴逻辑坐标 nWidth.

  • C/C++混合编程之extern “C”的使用示例

    前言 本文主要给大家介绍了关于C/C++混合编程extern "C"使用的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 首先要明白: C++号称是C语言的超集,也确实,从语言的基本语法上,C++是包含所有C语言的语法的,而且C++为了兼容C,连C语言的标准库也被纳入到C++的标准库中,比如在C++中我们仍然可以使用<stdio.h> ,它就是C++标准库的一部分(注意最好用新的标准<cstdio> ,而不是老的<stdio&g

  • Java网络编程之URL+URLconnection使用方法示例

    目录 HTTP GET和POST 从URLs到本地文件 在java.net包中包含两个有趣的类:URL类和URLConnection类.这两个类可以用来创建客户端到web服务器(HTTP服务器)的连接.下面是一个简单的代码例子: URL url = new URL("http://jenkov.com"); URLConnection urlConnection = url.openConnection(); InputStream input = urlConnection.getI

  • Java网络编程之TCP通信完整代码示例

    一.概述 Socket类是Java执行客户端TCP操作的基础类,这个类本身使用代码通过主机操作系统的本地TCP栈进行通信.Socket类的方法会建立和销毁连接,设置各种Socket选项. ServerSocket类是Java执行服务器端操作的基础类,该类运行于服务器,监听入站TCP连接,每个socket服务器监听服务器的某个端口,当远程主机的客户端尝试连接此端口时,服务器就被唤醒,并返回一个表示两台主机之间socket的正常Socket对象. 二.什么是TCP? TCP是一种面向连接的.可靠的.

  • Windows网络编程之winsock实现文件传输示例

    本文实例展示了Windows网络编程中winsock实现文件传输的方法,对于进行Windows下的winsock网络编程有一定的借鉴参考价值. 该程序代码主要是基于TCP流协议的winsock网络文件传输示例,采用Windows下的C语言编写.可以实现传递任何格式文件的文件传输功能. 具体实现代码如下: Server端代码如下: /************************************************************************* > File Na

  • java多线程编程之join方法的使用示例

    在上面的例子中多次使用到了Thread类的join方法.我想大家可能已经猜出来join方法的功能是什么了.对,join方法的功能就是使异步执行的线程变成同步执行.也就是说,当调用线程实例的start方法后,这个方法会立即返回,如果在调用start方法后后需要使用一个由这个线程计算得到的值,就必须使用join方法.如果不使用join方法,就不能保证当执行到start方法后面的某条语句时,这个线程一定会执行完.而使用join方法后,直到这个线程退出,程序才会往下执行.下面的代码演示了join的用法.

  • 深入分析Java并发编程之CAS

    在Java并发编程的世界里,synchronized 和 Lock 是控制多线程并发环境下对共享资源同步访问的两大手段.其中 Lock 是 JDK 层面的锁机制,是轻量级锁,底层使用大量的自旋+CAS操作实现的. 学习并发推荐<Java并发编程的艺术> 那什么是CAS呢?CAS,compare and swap,即比较并交换,什么是比较并交换呢?在Lock锁的理念中,采用的是一种乐观锁的形式,即多线程去修改共享资源时,不是在修改之前就加锁,而是乐观的认为没有别的线程和自己争锁,就是通过CAS的

  • python编程之requests在网络请求中添加cookies参数方法详解

    哎,好久没有学习爬虫了,现在想要重新拾起来.发现之前学习爬虫有些粗糙,竟然连requests中添加cookies都没有掌握,惭愧.废话不宜多,直接上内容. 我们平时使用requests获取网络内容很简单,几行代码搞定了,例如: import requests res=requests.get("https://cloud.flyme.cn/browser/index.jsp") print res.content 你没有看错,真的只有三行代码.但是简单归简单,问题还是不少的. 首先,这

  • Python编程之Re模块下的函数介绍

    re模块下的函数 compile(pattern):创建模式对象 import re pat=re.compile('A') m=pat.search('CBA') #等价于 re.search('A','CBA') print m <_sre.SRE_Match object at 0x9d690c8> #匹配到了,返回MatchObject(True) m=pat.search('CBD') print m None #没有匹配到,返回None(False) search(pattern,

  • C++编程之CString、string与、char数组的转换

    C++编程之CString.string与.char数组的转换 虽然网上关于CString,string,char数组的转换的文章一大堆,但是感觉很乱很杂,而且许多并不能真正达到目的,在此,我把自己调试通过的转换方法贴到这里,做个笔记. 编译环境:vs2008, Use Unicode Character Set //----------------ANSI字符串转换为UNICODE字符串----------------------// // 待转换的数组 char szDCBparam[50]

  • Linux网络编程之UDP Socket程序示例

    在网络传输协议中,TCP协议提供的是一种可靠的,复杂的,面向连接的数据流(SOCK_STREAM)传输服务,它通过三段式握手过程建立连接.TCP有一种"重传确认"机制,即接收端收到数据后要发出一个肯定确认的信号,发送端如果收到接收端肯定确认的信号,就会继续发送其他的数据,如果没有,它就会重新发送. 相对而言,UDP协议则是一种无连接的,不可靠的数据报(SOCK_DGRAM)传输服务.使用UDP套接口不用建立连接,服务端在调用socket()生成一个套接字并调用bind()绑定端口后就可

随机推荐