http://blog.csdn.net/imcainiao11/article/details/7369447

前言:以前见到extern "C"这样的语句,只是简单地知道跟外部链接有关,但是没有深刻理解它的意思。

首先,为什么要使用extern "C"修饰符?

C++调用其它语言的函数,由于编译器生成函数的机制不一样,所以需要经过特殊处理,才可以调用。调用C语言的函数,需要在函数声明的地方语句extern "C"。如果不使用该语句,在链接的时候,编译器就会报以下这种错误。

Test.obj : error LNK2019: 无法解析的外部符号 "void __cdecl DeleteStack(struct _Node *)" (?DeleteStack@@YAXPAU_Node@@@Z),该符号在函数 _main 中被引用。

然后是如何使用?

应该怎么使用该语句呢?

刚开始,我简单地在C++源文件的前面使用该语句声明,但是还是出错,而且是在编译阶段就报错。

  1. error C2732: 链接规范与“DeleteStack”的早期规范冲突。

为什么会出现这个错误呢?因为C++源文件已经引入了C的头文件,在头文件里,声明该函数时没有extern修饰,而这里有extern修饰,所以冲突了。解决的办法有两个。

一。在C头文件中加上extern修饰符。

直接加,也不行。因为C源文件也包含了这个头文件,当编译C源文件时,就会出现错误。所以,需要一种机制来区分是编译C还是C++文件。方法如下:

  1. #ifdef __cplusplus
  2. extern "C"
  3. #endif
  4. void DeleteStack(Stack stack);

因为在编译C++文件时,自动定义预处理器名字__cplusplus,而编译C时,没有该处理器名字。所以只有编译C++时,才有符号extern “C”。

此外,链接指示extern "C"有单个和复合两种形式。以上为单个形式,复合形式可以同时将几个函数声明为extern "C"

  1. extern "C" {
  2. void DeleteStack(Stack stack);
  3. void PrintStack(Stack stack);
  4. void Pop(Stack stack);
  5. }

加上预处理器名字如下:

  1. #ifdef __cplusplus
  2. extern "C" {
  3. #endif
  4. void DeleteStack(Stack stack);
  5. void PrintStack(Stack stack);
  6. void Pop(Stack stack);
  7. #ifdef __cplusplus
  8. }
  9. #endif

二。编写一个C++风格的头文件,在这里添加extern修饰符。

使用方法一,很简单。但是如果该头文件是别人写好,你无法修改。这个时候就要使用其它方法了。方法是定义C++自己的头文件,文件名为"CStack.h"

    1. // CStack.h
    2. extern "C" {
    3. #include "Stack.h";
    4. }

C++调用C函数的更多相关文章

  1. ng-repeat循环出来的部分调用同一个函数并且实现每个模块之间不能相互干扰

    使用场景:用ng-repeat几个部分,每个部分调用同一个函数,但是每个模块之间的功能不能相互干扰 问题:在用repeat实现.content块repeat的时候打算这样做:新建一个空的数组(nmbe ...

  2. 深入理解javascript系列(4):立即调用的函数表达式

    本文来自汤姆大叔 前言 大家学JavaScript的时候,经常遇到自执行匿名函数的代码,今天我们主要就来想想说一下自执行. 在详细了解这个之前,我们来谈了解一下“自执行”这个叫法,本文对这个功能的叫法 ...

  3. EC笔记,第二部分:9.不在构造、析构函数中调用虚函数

    9.不在构造.析构函数中调用虚函数 1.在构造函数和析构函数中调用虚函数会产生什么结果呢? #; } 上述程序会产生什么样的输出呢? 你一定会以为会输出: cls2 make cls2 delete ...

  4. EC笔记,第二部分:5.了解C++默默编写并调用哪些函数

    5.了解C++默默编写并调用哪些函数 1.C++空类 C++会为一个空类建立以下函数 (1).默认构造函数 (2).默认拷贝构造函数 (3).析构函数 (4).赋值运算符(如果成员包含引用类型或con ...

  5. C++构造函数中不能调用虚函数

    在构造函数中调用虚函数,并不会产生多态的效果,就跟普通函数一样. c++ primer 第四版中497页15.4.5构造函数和析构中的虚函数讲到,如果在构造函数或析构函数中调用虚函数,则运行的是为构造 ...

  6. ZeroMQ接口函数之 :zmq_errno – 返回errno的值给调用此函数的线程

    ZeroMQ 官方地址 :http://api.zeromq.org/4-0:zmq_errno zmq_errno(3)         ØMQ Manual - ØMQ/3.2.5 Name zm ...

  7. cocos2dx 3.x(获得父类的node型指针调用父类函数this->getParent())

    void CenterLayer::zhanzheng(CCObject* pSender){ ((GameScene*)this->getParent())->showLayer(Gam ...

  8. 09——绝不在构造和析构函数中调用virtual函数

    在base class构造期间,virtual函数不是virtual函数. 构造函数.析构函数中不要调用virtual函数.

  9. LR常用函数以及调用自定义函数

    2.LR常用函数以及调用自定义函数 2.1.LR常用函数以及对信息的判断 2.1.1. LR内部自定义函数 在LR脚本中定义变量和编写自定义函数,需将变量的声明放在脚本其他内容的上方,否则会提示[il ...

  10. lua如何调用C++函数

    第一步是定义函数.所有在Lua中被调用的C/C++函数将使用下面一类指针进行调用: typedef int (*lua_CFunction) (lua_State *L); 换句话说,函数必须要以Lu ...

随机推荐

  1. JQuery笔记汇总

    jQuery相关资料 官网: jQuery官网 在线API: jQuery在线API W3School:W3School-jQuery教程(中文版哦) 下载jQuery:jQuery各版本下载 jQu ...

  2. 树莓派(rasperberry pi 2)上装mysql远程无法访问

    于是组合关键字(树莓派 mysql)求百度问谷歌.未果.操刀自己来吧.检查mysql的配置文件 /etc/mysql/my.cnf 发现如下配置 # Instead of skip-networkin ...

  3. linux系统PXE+Kickstart自动安装系统

    一.PXEPXE(Pre-boot Execution Environment,预启动执行环境)是由Intel公司开发的最新技术,工作于Client/Server的网络模式,支持工作站通过网络从远端服 ...

  4. 基于AQS的锁

    锁分为独占锁和共享锁,它们的主要实现都是依靠AbstractQueuedSynchronizer,这个类只提供一系列公共的方法,让子类来调用.基于我了解不深,从这个类的属性,方法,和独占锁的获取方式去 ...

  5. 数据库热备份工具innobackupex的安装

    Xtrabackup是由percona开发的一个开源软件,此软件可以说是innodb热备工具ibbackup的一个开源替代品. 这个软件是由2个部分组成的:xtrabackup和innobackupe ...

  6. Tomcat7开启CGI支持的方法

    tomcat默认没有开启cgi支持,因此有了tomat开启cgi的探索.因为原本对tomcat没多了解,所以中间或多或少走了点弯路.还好最终配置成功了,现在jy也用上这个方法了.    该方法在apa ...

  7. IELTS Writing Tips

  8. crontab 系列

    crontab是一个很方便的在unix/linux系统上定时(循环)执行某个任务的程序使用cron服务,用 service crond status 查看 cron服务状态,如果没有启动则 servi ...

  9. UI设计趋势:渐变设计风格重新回归主流

    在扁平化设计刚刚兴起之时,渐变是设计师们避之不及的设计手法,然而今天它已经正式回归.几乎是在一夜之间,无数的网站开始使用渐变色. 从背景到图片上的色彩叠加,包括UI元素上所遮盖的色彩,所有的这一切都表 ...

  10. Java基础---MD5和BASE64

    package cn.peter; import sun.misc.BASE64Encoder; import java.io.UnsupportedEncodingException; import ...