Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1825009
  • 博文数量: 159
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 5649
  • 用 户 组: 普通用户
  • 注册时间: 2013-01-23 18:56
个人简介

将晦涩难懂的技术讲的通俗易懂

文章分类

全部博文(159)

文章存档

2019年(13)

2018年(19)

2017年(9)

2016年(26)

2015年(18)

2014年(54)

2013年(20)

分类: C/C++

2014-04-14 21:33:02

首先,混合编程不是指在同一个文件里写CC++

混合编程包括:1C++引用C的头文件;2g++生成的.ogcc生成的.o相链接。

一、externC”的作用(最重点)

    1. extern "C"的真实目的是实现类CC++的混合编程。extern C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数。extern C”后面的函数不使用的C++的名字修饰,而是用C。这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数。

    2.C++语言支持函数重载,C语言不支持函数重载。函数被C++编译后在库中的名字与C语言的不同。假设某个函数的原型为:void foo(int x, int y);该函数被C编译器编译后在库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字。C++提供了C连接交换指定符号externC”来解决名字匹配问题。

    3.extern "C"限定的函数或变量是extern类型的;externC/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。被extern "C"修饰的变量和函数是按照C语言方式编译和连接的。   

     4.extern对应的关键字是static,被它修饰的全局变量和函数只能在本模块中使用。因此,一个函数或变量只可能被本模块使用时,其不可能被extern C”修饰。

二、externC”与__cplusplus


点击(此处)折叠或打开

  1. #ifdef __cplusplus
  2.        extern "C" {
  3.        #endif
  4.        #ifdef __cplusplus
  5.        }
  6.        #endif


    _cplusplus标示符用来判断程序是用c还是c++编译程序编译的。当编译c++程序时,这个标示符会被定义,编译c程序时,不会定义。C++文档的头文件中,上面代码的意思是:如果是C++文件(*.cpp)后缀,则使用extern C”,在C++项目中应用的非常广泛。

三、C调用C++函数(接口)

1. cpp头文件:animal.h


点击(此处)折叠或打开

  1. #ifndef __ANIMAL_H__ //防止被重复包含
  2. #define __ANIMAL_H__
  3. class ANIMAL{
  4. public:
  5.         ANIMAL(char* );
  6.         ~ANIMAL();
  7.         char* getname(void);
  8. private:
  9.         char* name;
  10. };
  11. #endif // __ANIMAL_H__


2. cpp文件:animal.cpp

点击(此处)折叠或打开

  1. #include "animal.h"
  2. #include <iostream>
  3. #include <string.h>
  4. using namespace std;
  5. ANIMAL::ANIMAL(char* data)//构造函数
  6. { name = new char[64];
  7.         strcpy(name, data);
  8. }
  9. ANIMAL::~ANIMAL() //析构函数
  10. {
  11.        if(name)
  12.       {
  13.         delete[] name;
  14.         name = NULL;
  15.       }
  16. }
  17. char* ANIMAL::getname(void)
  18. { 
  19.     return name;
  20. }


3. 中间层cpp头文件:middle.h


点击(此处)折叠或打开

  1. #ifndef __MIDDLE_H__
  2. #define __MIDDLE_H__
  3. #ifdef __cplusplus
  4. extern "C"
  5. {
  6. #endif
  7. void print(void);
  8. #ifdef __cplusplus
  9. }
  10. #endif
  11. #endif


注:middle.h需要包含在.C文件中,因此middle.h中不能包含含有C++关键字(如class)的animal.h.

4. 中间层cpp文件:middle.cpp


点击(此处)折叠或打开

  1. #include "middle.h"
  2. #include "animal.h"
  3. #include <iostream>
  4. using namespace std;
  5. void print(void) //对外接口
  6. {
  7.         ANIMAL animal("dog");
  8.         char* animal_name = animal.getname();
  9.         cout << "animal name is :" << animal_name << endl;
  10. }


注:接口函数需要用到C++中的class,因此需要包含animal.h.

5. C文件:test.c


点击(此处)折叠或打开

  1. #include "middle.h"
  2. int main(int argc, char *argv[])
  3. {
  4. print();
  5. return 0;
  6. }


6. Makefile


main: test.o animal.o middle.o

gcc -o test  middle.o  animal.o test.o -lstdc++

animal.o:animal.h

g++ -c animal.cpp

middle.o:middle.h

g++ -c middle.cpp

clean:

rm -f middle.o animal.o test test.o


说明:

(1) .C文件中包含的直接或间接头文件中不要有c++关键字,因为.C文件是c编译器编译的,无法识别C++关键字。

(2) .c文件要想使用cpp中的class,需要在一个非成员函数中,而这个非成员函数是在cpp文件中实现的(.c文件不识别class)。

(3) gcc连接时需要加上-lstdc++(使用c++库),因为默认会使用c动态库,而c库中没有c++的一些函数。

整个上述例子的关系可用图形表示为:


绿色:必须用c++编译,要么是cpp文件,要么含有class关键字

蓝色:c文件

橙色:中间衔接头文件(与c++无关)

注:C调用C++还有一种包裹函数法。

测试:


四、C++调用C函数

应该这个比较简单,我就不多写了,就直接写代码。

共有三个文件:1.h 1.c  main.cpp

[root@localhost aa]#cat 1.h

#ifndef _1__H_

#define _1__H_

extern void print(char* );

#endif

[root@localhost aa]#cat 1.c

#include 

#include "1.h"

void print(char* data)

{

        printf("%s\n",  data);

}

[root@localhost aa]#cat main.cpp

extern "C"{

#include "1.h"}

int main(void)

{

        print(“hello,world\n”);

        return 0;

}

gcc –c 1.c

g++ main.cpp 1.o

    接着./a.out,又可以出现我们神奇的hello,world了,C++调用C代码很简单。

阅读(1192) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~
评论热议
请登录后评论。

登录 注册