c和c++相互调用

来源:互联网 发布:数值分析软件 编辑:程序博客网 时间:2024/04/25 15:48
extern "C"的惯用法
  (1)在C++中引用C语言中的函数和变量,在包含C语言头文件(假设为cExample.h)时,需进行下列处理:
        extern "C"
       {
        #include "cExample.h"                                 
       }
  而在C语言的头文件中,对其外部函数只能指定为extern类型,C语言中不支持extern "C"声明,在.c文件中包含了extern "C"时会出现编译语法错误。
  笔者编写的C++引用C函数例子工程中包含的三个文件的源代码如下:
        
      #ifndef C_EXAMPLE_H
      #define C_EXAMPLE_H
       extern int add(int x,int y);
      #endif

      
     #include "cExample.h"
     int add( int x, int y )
     {
            return x + y;
     }
     // c++实现文件,调用add:cppFile.cpp
     extern "C" 
     {
     #include "cExample.h"
     }
     int main(int argc, char* argv[])
     {
            add(2,3); 
            return 0;
      }

      如果C++调用一个C语言编写的.DLL时,当包括.DLL的头文件或声明接口函数时,应加extern "C" { }

    (2)在C中引用C++语言中的函数和变量时,C++的头文件需添加extern "C",但是在C语言中不能直接引用声明了extern "C"的该头文件,应该仅在C文件中将C++中定义的extern "C"函数声明为extern类型。
  笔者编写的C引用C++函数例子工程中包含的三个文件的源代码如下:

        //C++头文件 cppExample.h
        #ifndef CPP_EXAMPLE_H
        #define CPP_EXAMPLE_H
        extern "C" int add( int x, int y );
        #endif
        //C++实现文件 cppExample.cpp
        #include "cppExample.h"
        int add( int x, int y )
        {
                return x + y;
        }
        
       extern int add( int x, int y );
       int main( int argc, char* argv[] )
      {
             add( 2, 3 ); 
             return 0;
       }

  如果深入理解了第3节中所阐述的extern "C"在编译和连接阶段发挥的作用,就能真正理解本节所阐述的从C++引用C函数和C引用C++函数的惯用法。对第4节给出的示例代码,需要特别留意各个细节。

对于以上C++调用C语言函数会出现以下现象:

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

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

例如

int add(int , int)==>add@@YAHHH@Z,

float add(float , float )==>add@@YAMMM@Z,

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

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

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

#ifndef __H#define __H#ifdef __cplusplusextern "C" {#endifextern 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 __cplusplusextern "C" {#endifextern int add(int, int);#ifdef __cplusplus}#endif#endif /* _C_H_ */ 

这样编译

/*-----------c.c--------------*/
int
 add(int x, int y){
return
 x+y;
}


0 0
原创粉丝点击