C++调用C函数
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++源文件的前面使用该语句声明,但是还是出错,而且是在编译阶段就报错。
- error C2732: 链接规范与“DeleteStack”的早期规范冲突。
为什么会出现这个错误呢?因为C++源文件已经引入了C的头文件,在头文件里,声明该函数时没有extern修饰,而这里有extern修饰,所以冲突了。解决的办法有两个。
一。在C头文件中加上extern修饰符。
直接加,也不行。因为C源文件也包含了这个头文件,当编译C源文件时,就会出现错误。所以,需要一种机制来区分是编译C还是C++文件。方法如下:
- #ifdef __cplusplus
- extern "C"
- #endif
- void DeleteStack(Stack stack);
因为在编译C++文件时,自动定义预处理器名字__cplusplus,而编译C时,没有该处理器名字。所以只有编译C++时,才有符号extern “C”。
此外,链接指示extern "C"有单个和复合两种形式。以上为单个形式,复合形式可以同时将几个函数声明为extern "C"
- extern "C" {
- void DeleteStack(Stack stack);
- void PrintStack(Stack stack);
- void Pop(Stack stack);
- }
加上预处理器名字如下:
- #ifdef __cplusplus
- extern "C" {
- #endif
- void DeleteStack(Stack stack);
- void PrintStack(Stack stack);
- void Pop(Stack stack);
- #ifdef __cplusplus
- }
- #endif
二。编写一个C++风格的头文件,在这里添加extern修饰符。
使用方法一,很简单。但是如果该头文件是别人写好,你无法修改。这个时候就要使用其它方法了。方法是定义C++自己的头文件,文件名为"CStack.h"
- // CStack.h
- extern "C" {
- #include "Stack.h";
- }
C++调用C函数的更多相关文章
- ng-repeat循环出来的部分调用同一个函数并且实现每个模块之间不能相互干扰
使用场景:用ng-repeat几个部分,每个部分调用同一个函数,但是每个模块之间的功能不能相互干扰 问题:在用repeat实现.content块repeat的时候打算这样做:新建一个空的数组(nmbe ...
- 深入理解javascript系列(4):立即调用的函数表达式
本文来自汤姆大叔 前言 大家学JavaScript的时候,经常遇到自执行匿名函数的代码,今天我们主要就来想想说一下自执行. 在详细了解这个之前,我们来谈了解一下“自执行”这个叫法,本文对这个功能的叫法 ...
- EC笔记,第二部分:9.不在构造、析构函数中调用虚函数
9.不在构造.析构函数中调用虚函数 1.在构造函数和析构函数中调用虚函数会产生什么结果呢? #; } 上述程序会产生什么样的输出呢? 你一定会以为会输出: cls2 make cls2 delete ...
- EC笔记,第二部分:5.了解C++默默编写并调用哪些函数
5.了解C++默默编写并调用哪些函数 1.C++空类 C++会为一个空类建立以下函数 (1).默认构造函数 (2).默认拷贝构造函数 (3).析构函数 (4).赋值运算符(如果成员包含引用类型或con ...
- C++构造函数中不能调用虚函数
在构造函数中调用虚函数,并不会产生多态的效果,就跟普通函数一样. c++ primer 第四版中497页15.4.5构造函数和析构中的虚函数讲到,如果在构造函数或析构函数中调用虚函数,则运行的是为构造 ...
- ZeroMQ接口函数之 :zmq_errno – 返回errno的值给调用此函数的线程
ZeroMQ 官方地址 :http://api.zeromq.org/4-0:zmq_errno zmq_errno(3) ØMQ Manual - ØMQ/3.2.5 Name zm ...
- cocos2dx 3.x(获得父类的node型指针调用父类函数this->getParent())
void CenterLayer::zhanzheng(CCObject* pSender){ ((GameScene*)this->getParent())->showLayer(Gam ...
- 09——绝不在构造和析构函数中调用virtual函数
在base class构造期间,virtual函数不是virtual函数. 构造函数.析构函数中不要调用virtual函数.
- LR常用函数以及调用自定义函数
2.LR常用函数以及调用自定义函数 2.1.LR常用函数以及对信息的判断 2.1.1. LR内部自定义函数 在LR脚本中定义变量和编写自定义函数,需将变量的声明放在脚本其他内容的上方,否则会提示[il ...
- lua如何调用C++函数
第一步是定义函数.所有在Lua中被调用的C/C++函数将使用下面一类指针进行调用: typedef int (*lua_CFunction) (lua_State *L); 换句话说,函数必须要以Lu ...
随机推荐
- hive中拉链表
在有些情况下,为了保持历史的一些状态,需要用拉链表来做,这样做目的在可以保留所有状态的情况下可以节省空间. 拉链表适用于以下几种情况吧 数据量有点大,表中某些字段有变化,但是呢变化的频率也不是很高,业 ...
- 配置 Haproxy 防范 DDOS 攻击
作为 load balancer, Happroxy 常常作为服务器的前端,向外界用户提供服务的入口,如果能在入口处处理安全相关问题,将极大简化后端的设计.事实上,Haproxy 不仅仅是一款开源出色 ...
- C#中string在内存中是如何表示的
不知道你是否有过和我一样的疑问,不同编码的字符串是如何存储在运行时的内存中的呢,计算机在操作string类型的对象时,如何知道这个string是什么编码呢?和文本文件那样有类似BOM的东东在strin ...
- SQL 查询所有表名、字段名、类型、长度、存储过程、视图
-- 获得存储过程创建语句 select o.xtype,o.name,cm.text from syscomments cm inner join sysobjects o on o.id=cm.i ...
- Django中载入javascript、css的操作
url.py中的设置: 导入模块 from django.conf import settings (r'^js/(?P<path>.*)$','django.views.static. ...
- Python数据库备份脚本
Python数据库备份脚本 #!/usr/bin/env python # author: liudong # -*- coding: utf-8 -*- # filename: db_bak.py ...
- PostgreSQL9.2安装和配置指南
本文只介绍PostgreSQL9.2在centos上的安装和配置过程 1.执行yum 命令安装PostgreSQL yum install postgresql-server 2.初始化Postgre ...
- Breakpoint is not hit
新拿到一个Silverlight项目,能够正常运行,但是一旦运行起来,断点处由实心点变成了空心的,并警告:The breakpoint will not currently be hit. No sy ...
- SQL Server更新表(用一张表的数据更新另一张表的数据)
a) 写法轻松,更新效率高: update table1 set field1=table2.field1,field2=table2.field2 from table2 where table1. ...
- CC1310电源
CC1310的电源好扯,把目前遇到的问题记录一下 1 全局LDO和DCDC的输出电压问题 手册上要求的VDDR和VDDR_RF的电压范围是1.7~1.95V,但实际测试时, 在接收状态下无论是全局LD ...