extern c详解(下)

文章修改自: 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的好处。 

你可能感兴趣的:(c,header,语言,float,编译器,Signal)