C和C++混合编程

extern "C"表示编译生成的内部符号名使用C约定。C++支持函数重载,而C不支持,两者的编译规则也不一样。函数被C++编译后在符号库中的名字与C语言的不 同。例如,假设某个函数的原型为:void foo( int x, int y ); 该函数被C编译器编译后在符号库中的名字可能为_foo,而C++编译器则会产生像_foo_int_int之类的名字(不同的编译器可能生成的名字不 同,但是都采用了相同的机制,生成的新名字称为“mangled name”)。_foo_int_int这样的名字包含了函数名、函数参数数量及类型信息,C++就是靠这种机制来实现函数重载的。下面以例子说明,如何 在C++中使用C的函数,或者在C中使用C++的函数。
 一://C++引用C函数的例子(C++调用C,extern "C" 的作用是:让C++连接器找调用函数的符号时采用C的方式 如)
//test.c
#include
void mytest()
{
 printf("mytest in .c file ok\n");
}
//main.cpp
extern "C"
{
void mytest();
}
int main()
{
 mytest();
 return 0;
}
上述也可以加个头文件
//test.h
void mytest()
在后在main.cpp中extern "C"
{
#include “test.h”
}

二://在C中引用C++函数(C调用C++,使用extern "C"则是告诉编译器把cpp文件中extern "C"定义的函数依照C的方式来编译封装接口,当然接口函数里面的C++语法还是按C++方式编译)
在C中引用C++语言中的函数和变量时,C++的函数或变量要声明在extern "C"{}里,但是在C语言中不能使用extern
"C",否则编译出错。(出现错误: error C2059: syntax error :
‘string‘,这个错误在网上找了很久,国内网站没有搜到直接说明原因的,原因是extern
"C"是C++中的关键词,不是C的,所有会出错。那怎么用?看本文,或者搜extern "C"!)
//test.cpp
#include
extern "C"
{
void mytest()
{
 printf("mytest in .cpp file ok\n");
}
}
//main.c
void mytest();
int main()
{
 mytest();
 return 0;
}

三.//综合使用
一般我们都将函数声明放在头文件,当我们的函数有可能被C或C++使用时,我们无法确定被谁调用,使得不能确定是否要将函数声明在extern "C"里,所以,我们可以添加
#ifdef __cplusplus
 extern "C"
 {
 #endif
//函数声明
#ifdef __cplusplus
 }
 #endif
这样的话这个文件无论是被C或C++调用都可以,不会出现上面的那个错误:error C2059: syntax error : ‘string‘。
如果我们注意到,很多头文件都有这样的用法,比如string.h,等等。
//test.h
#ifdef __cplusplus
#include
using namespace std;
 extern "C"
 {
 #endif
void mytest();
#ifdef __cplusplus
 }
 #endif
这样,可以将mytest()的实现放在.c或者.cpp文件中,可以在.c或者.cpp文件中include "test.h"后使用头文件里面的函数,而不会出现编译错误。
//test.c
#include "test.h"
void mytest()
{
#ifdef __cplusplus
 cout << "cout mytest extern ok " << endl;
#else
 printf("printf mytest extern ok n");
#endif
}
//main.cpp
#include "test.h"
int main()
{
 mytest();
 return 0;
}
关于C++引用C函数和变量的例子还有一个(来自网上,可以google)
两个文件:
c文件:C.c
***********************************************
int external="5"; //全局变量,缺省为extern。
int func() //全局函数,缺省为extern。
{
return external;
}
***********************************************
cpp文件:CPP.cpp
***********************************************
#include "iostream"
using namespace std;
#ifdef __cplusplus
extern "C"
{
#endif
extern int external; //告诉编译器extern是在别的文件中定义的int,这里并不会为其分配存储空间。
extern int func(); //虽然这两个都是在extern "C"的{}里,但是仍然要显式指定extern,否则报错。
#ifdef __cplusplus //不仅仅是函数,变量也要放在extern "C"中。
}
#endif

void main(void)
{
cout<<"the value of external in c file is: "< external=10;
cout<<"after modified in cpp is : "< }
*********************************************** 
extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字.,它告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。
1。对于extern变量来说,仅仅是一个变量的声明,其并不是在定义分配内存空间。如果该变量定义多次,会有连接错误
2。通常,在模块的头文件中对本模块提供给其它模块引用的函数和全局变量以关键字extern声明。也就是说c文件里面定义,如果该函数或者变量与开放给
外面,则在h文件中用extern加以声明。所以外部文件只用include该h文件就可以了。而且编译阶段,外面是找不到该函数的,但是不报错。
link阶段会从定义模块生成的目标代码中找到此函数。
3。与extern对应的关键字是static,被它修饰的全局变量和函数只能在本模块中使用。

C++调用C   

以下是假设旧的C程序库

C的头文件

/*-----------c.h--------------*/

#ifndef _C_H_

#define _C_H_

extern int add(int x, int y);

#endif

C的源文件

/*-----------c.c--------------*/

int add(int x, int y){

return x+y;

}

C++的调用

/*-----------cpp.cpp--------------*/

#include "c.h"

void main()

{

add(1, 0);

}

这样编译会产生错误cpp.obj : error LNK2001: unresolved external symbol "int
__cdecl add(int,int)"
([[email protected]@[email protected]][email protected]@[email protected][/email]),原因是找不到add的目标模块

这才令我想起C++重载的函数命名方式和C函数的命名方式,让我们回顾一下:C中函数编译后命名会在函数名前加以"_",比如add函数编译成obj文件时的实际命名为_add,而c++命名则不同,为了实现函数重载同样的函数名add因参数的不同会被编译成不同的名字

例如

int add(int , int)==>[email protected]@[email protected],

float add(float , float )==>[email protected]@[email protected],

以上是VC6的命名方式,不同的编译器会不同,总之不同的参数同样的函数名将编译成不同目标名,以便于函数重载是调用具体的函数。

编译cpp.cpp中编译器在cpp文件中发现add(1, 0);的调用而函数声明为extern int add(int x, int
y);编译器就决定去找[[email protected]@[email protected]][email protected]@[email protected][/email],可惜他找不到,因为C的源文件把
extern int add(int x, int y);编译成_add了;

为了解决这个问题C++采用了extern "C",这就是我们的主题,想要利用以前的C程序库,那么你就要学会它,我们可以看以下标准头文件你会发现,很多头文件都有以下的结构

#ifndef __H

#define __H

#ifdef __cplusplus

extern "C" {

#endif

extern int f1(int, int);

extern int f2(int, int);

extern int f3(int, int);

#ifdef __cplusplus

}

#endif

#endif /*__H*/

如果我们仿制该头文件可以得到

#ifndef _C_H_

#define _C_H_

#ifdef __cplusplus

extern "C" {

#endif

extern int add(int, int);

#ifdef __cplusplus

}

#endif

#endif /* _C_H_ */

这样编译

/*-----------c.c--------------*/

int add(int x, int y){

return x+y;

}

这时源文件为*.c,__cplusplus没有被定义,extern "C" {}这时没有生效对于C他看到只是extern int add(int, int);

add函数编译成_add(int, int);

而编译c++源文件

/*-----------cpp.cpp--------------*/

#include "c.h"

void main()

{

add(1, 0);

}

这时源文件为*.cpp,__cplusplus被定义,对于C++他看到的是extern "C" {extern int add(int,
int);}编译器就会知道 add(1, 0);调用的C风格的函数,就会知道去c.obj中找_add(int,
int)而不是[[email protected]@[email protected]][email protected]@[email protected][/email];

这也就为什么DLL中常看见extern "C" {},windows是采用C语言编制他首先要考虑到C可以正确调用这些DLL,而用户可能会使用C++而extern "C" {}就会发生作用

当原来的C语言写的头文件里面没有考虑这个问题的时候,可以写成这样:

#include

#include

extern "C" {

#include "sift.h"

#include "imgfeatures.h"

#include "kdtree.h"

#include "utils.h"

#include "xform.h"

}

这样就可以在C++里面用别人写的C语言的东西了。

时间: 2024-10-06 02:42:42

C和C++混合编程的相关文章

C++与Java混合编程

http://www.cnblogs.com/lxshanye/p/3209542.html 现在的程序员,不再像以前一样,掌握一种编程语言就可以混得有模有样了,现实的情况是,真实的项目中,通常是涉及多种编程语言,举几个简单的例子,一个软件为了快速开发,可能是使用Delphi或VB作为界面开发首选语言,底层的指令或核心算法,会使用C/C++处理,涉及数据处理的时候,为了安全和快速开发,会使用Javascript或Python等脚本语言实现数据分析处理.因此,开发者应该学习或掌握语言混合编程. C

用c/c++混合编程方式为ios/android实现一个自绘日期选择控件(一)

本文为原创,如有转载,请注明出处:http://www.cnblogs.com/jackybu 前言 章节: 1.需求描述以及c/c++实现日期和月历的基本操作 2.ios实现自绘日期选择控件 3.android实现自绘日期选择控件 目的: 通过一个相对复杂的自定义自绘控件来分享: 1.ios以及android自定义自绘控件的开发流程 2.objc与c/c++混合编程 3.android ndk的环境配置,android studio ndk的编译模式,swig在android ndk开发中的作

【5.1送礼】国内第一部Matlab和C#.Net混合编程入门级视频教程【完全免费】

上一次写博客很久了,一直在忙彩票分析系统架构的事情,写博客真是件费神的事情,非常花时间.今天抽空发布这篇博客,是为了开源一部自己录制的视频教程-Matlab和C#.Net混合编程视频教程[入门级].下面说说这部视频教程的来由和一些事情,想获取的仔细看看,别忘了点[推荐]哦! 一.为啥要开源 1.1 视频的来源 这部视频教程是在2012年年底闲时比较多,当初也是很多朋友,网友提出这个Matlab.Net混合编程入门比较难,没有资料,所有就特意录制了一部比较简单的视频教程.并有条件的对广大网友免费开

Qt Quick 之 QML 与 C++ 混合编程详解

Qt Quick 技术的引入,使得你能够快速构建 UI ,具有动画.各种绚丽效果的 UI 都不在话下.但它不是万能的,也有很多局限性,原来 Qt 的一些技术,比如低阶的网络编程如 QTcpSocket ,多线程,又如 XML 文档处理类库 QXmlStreamReader / QXmlStreamWriter 等等,在 QML 中要么不可用,要么用起来不方便,所以呢,很多时候我们是会基于这样的原则来混合使用 QML 和 C++: QML 构建界面, C++ 实现非界面的业务逻辑和复杂运算. 请给

extern &quot;C&quot; 的含义:????实现C++与C及其它语言的混合编程

C++中extern "C"的设立动机是实现C++与C及其它语言的混合编程. C++为了支持函数的重载,C++对全局函数的处理方式与C有明显的不同.对于函数void foo( int x, int y );该函数被C编译器编译后在符号库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字. extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用. 通常,在模块的头文件中对本

Matlab.NET混合编程调用Figure窗体

原文:[原创]Matlab.NET混合编程调用Figure窗体 1.前言 做Matlab.NET混合编程好几年了,虽然Matlab很多函数忘记得差不多了,但基本的东西还是能熟练使用.特别是在C#调用Matlab函数这方面,积累了比较多的经验,和使用经验密切相关.根据很多朋友经常遇到的WinForm窗体混编调用Matlab的Figure的问题,花了一些功夫,把这个封装为C#控件,使得大家可以很容易调用Matlab的Figure了. 2.Matlab.NET混合编程概述 这方面就不仔细阐述了,主要是

[转] Matlab与C++混合编程,添加OpenCV库

原文地址 峰回璐转 最近在做运动医学软件优化工作,此款软件框架及算法语言全由matlab实现,虽然matlab矩阵运算.数值计算能力强大,但速度让人难以忍 受.软件立刻移植到C++上又不太实际,故采用联合编程的方式,速度难以容忍的算法交给C++实现,C++在实现代码的过程中某些数值计算及图像处理算法 调opencv库函数. 在网上有很多matlab编写mex函数调用opencv库的方法,但都不能直接拿来.经过一步步试验,修改,最终完成,现将过程及内容记录下来留给后来人参考. 第一步: (参考参考

C#和matlab混合编程

C#和MatLab的混合编程,充分利用了winform的直观显示和matlab的强大计算能力.在此以一个小例子的形式给大家讲述一下二者混合编程的实现. 一.软件的配置说明 C#版本:VS2010        matlab版本:matlab2013a 二.把 matlab函数编译成dll文件 2.1首先写一个函数的.m文件(如下函数MatrixOpera实现两个矩阵的相加和相减) %--------------------------------------------------------

c#与matlab混合编程探索

以下讲述如何使用c#来调用matlab函数实现北斗定位算法的仿真 1.准备 首先需要matlab2010,vs2010(其他版本是否可行,未知),另外需要安装matlab的辅助工具MCRInstaller(该工具无需下载,在安装好的matlab程序包中可以找到,例如:E:\matlab 2010\toolbox\compiler\deploy\win32) 2.准备matlab程序 上述截图是我的定位程序所涉及到的函数 3.matlab程序处理为dll文件,供c#调用,处理的基本步骤如下: (1

java和c++混合编程尝试

下载源代码 现在的程序员,不再像以前一样,掌握一种编程语言就可以混得有模有样了,现实的情况是,真实的项目中,通常是涉及多种编程语言,举几个简单的例子,一个软件为了快速开发,可能是使用 Delphi 或 VB 作为界面开发首选语言,底层的指令或核心算法,会使用 C/C++ 处理,涉及数据处理的时候,为了安全和快速开发,会使用 Javascript 或 Python 等脚本语言实现数据分析处理.因此,开发者应该学习或掌握语言混合编程. C++ 和 Java 是主流的两种编程语言,但是现在整个网上对实