注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

民主与科学

独立之人格,自由之思想

 
 
 

日志

 
 

extern c详解(下)  

2011-07-09 07:40:57|  分类: C和C++语言 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
文章修改自:http://wenku.baidu.com/view/8872c444b307e87101f69650.html
三、C和C++互相调用
我们既然知道extern "C"是实现的类C和C++的混合编程。下面我们就分别介绍如何在C++中调用C的代码、C中调用C++的代码。首先要明白C和C++互相调用,你得知道它们之间的编译和连接差异,及如何利用extern "C"来实现相互调用。
3.1、C++的编译和连接
C++是一个面向对象语言(虽不是纯粹的面向对象语言),它支持函数的重载,重载这个特性给我们带来了很大的便利。为了支持函数重载的这个特性,C++编译器实际上将下面这些重载函数:
1 void print(int i); 
2 void print(char c); 
3 void print(float f); 
4 void print(char* s);
编译为:
1 _print_int 
2 _print_char 
3 _print_float 
4 _pirnt_string
这样的函数名,来唯一标识每个函数。不同的编译器实现可能不一样,但是都是利用这种机制。所以当连接是调用print(3)时,它会去查找_print_int(3)这样的函数。正是因为这点,重载被认为不是多态,多态是运行时动态绑定(“一种接口多种实现”),如果硬要认为重载是多态,它顶多是编译时“多态”。
C++中的变量,编译也类似,如全局变量可能编译g_xx,类变量编译为c_xx等。连接是也是按照这种机制去查找相应的变量。
3.2、C的编译和连接
C语言中并没有重载和类这些特性,故并不像C++那样print(int i),会被编译为_print_int,而是直接编译为_print等。因此如果直接在C++中调用C的函数会失败,因为连接是调用C中的print(3)时,它会去找_print_int(3)。因此extern "C"的作用就体现出来了。
3.3、C++中调用C的代码
假设一个C的头文件cHeader.h中包含一个函数print(int i),为了在C++中能够调用它,必须要加上extern关键字(原因在extern关键字那节已经介绍)。它的代码如下:
#ifndef C_HEADER 
#define C_HEADER
extern void print(int i); 
#endif C_HEADER
相对应的实现文件为cHeader.c的代码为:
#include <stdio.h> 
#include "cHeader.h" 
void print(int i) 
   printf("cHeader %d\n",i); 
}
现在C++的代码文件C++.cpp中引用C中的print(int i)函数:
extern "C"
#include "cHeader.h" 
int main(int argc,char** argv) 
   print(3); 
   return 0; 
3.4、C中调用C++的代码
现在换成在C中调用C++的代码,这与在C++中调用C的代码有所不同。如下在cppHeader.h头文件中定义了下面的代码:
#ifndef CPP_HEADER 
#define CPP_HEADER   
extern "C" void print(int i); 
#endif CPP_HEADER
相应的实现文件cppHeader.cpp文件中代码如下:
#include "cppHeader.h" 
#include <iostream> 
using namespace std; 
void print(int i) 
   cout<<"cppHeader "<<i<<endl; 
}
在C的代码文件c.c中调用print函数:
extern int print(int i); 
int main(int argc,char** argv) 
   print(3); 
   return 0; 
}
注意:在C的代码文件中直接#include "cppHeader.h"头文件,编译出错。而且如果不加extern int print(int i)编译也会出错。
四、同一模块中时C和C++混合使用
如果C和C++在同一模块中,那么他们可以直接混合使用,即C的函数和变量可以直接在C++中使用,C++的函数和变量也可以直接在C中使用
如下例
#include <stdio.h> 
#include <iostream>
using namespace std;
typedef int (*FT) (const void* ,const void*);//style of C++ 
int x=0; 
extern "C"
    typedef int (*CFT) (const void*,const void*);//style of C 
    void qsort(void* p,size_t n,size_t sz,CFT cmp)//style of C 
{
x=1;
cout<<"Hello"<<endl;
int result=cmp(0,0);
printf("in qsort,result is %d\n",result);
}
int y=0;
class A{
public:
A()
{
log(100);
log(10,20);
}
void log(int i)
{
cout<<"log"<<i<<endl;
};
void log(long a,long b)
{
cout<<"log a:"<<a<<"b:"<<b<<endl;
};
};
}
void isort(void* p,size_t n,size_t sz,FT cmp)//style of C++ 
{
y=1;
int result=cmp(0,0);
printf("in Isort,result is %d\n",result);
}
void xsort(void* p,size_t n,size_t sz,CFT cmp)//style of C 
{
int result=cmp(0,0);
printf("in Xsort,result is %d\n",result);
}
extern "C" void ysort(void* p,size_t n,size_t sz,FT cmp)//style of C 
{
int result=cmp(0,0);
printf("in Ysort,result is %d\n",result);
int compare(const void*,const void*)//style of C++ 
{
return 1;
}
extern "C" int ccomp(const void*,const void*)//style of C
{
return 0;
}
void f(char* v,int sz) 
{
A a;
a.log(1000);
    qsort(v,sz,1,&compare);//ok
    qsort(v,sz,1,&ccomp);//ok 
      
    isort(v,sz,1,&compare);//ok 
    isort(v,sz,1,&ccomp);//ok
    
    xsort(v,sz,1,&compare);//ok 
    xsort(v,sz,1,&ccomp);//ok
    
    ysort(v,sz,1,&compare);//ok 
    ysort(v,sz,1,&ccomp);//ok  
}
int main()
{
f(0,0);
return 0;
}
编译命令
g++  test.cpp -o test.exe
注意typedef int (*FT) (const void* ,const void*),表示定义了一个函数指针的别名FT,这种函数指针指向的函数有这样的特征:返回值为int型、有两个参数,参数类型可以为任意类型的指针(因为为void*)。
最典型的函数指针的别名的例子是,信号处理函数signal,它的定义如下:
1 typedef void (*HANDLER)(int); 
2 HANDLER signal(int ,HANDLER);
上面的代码定义了信函处理函数signal,它的返回值类型为HANDLER,有两个参数分别为int、HANDLER。 这样避免了要这样定义signal函数:
void (*signal (int ,void(*)(int) ))(int)
比较之后可以明显的体会到typedef的好处。 
  评论这张
 
阅读(721)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017