C&C++混合编程
首先,混合编程不是指在同一个文件里写C与C++。
混合编程包括:1,C++引用C的头文件;2,g++生成的.o与gcc生成的.o相链接。
一、extern“C”的作用(最重点)
1. extern "C"的真实目的是实现类C和C++的混合编程。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连接交换指定符号extern“C”来解决名字匹配问题。
3.被extern "C"限定的函数或变量是extern类型的;extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。被extern "C"修饰的变量和函数是按照C语言方式编译和连接的。
4.与extern对应的关键字是static,被它修饰的全局变量和函数只能在本模块中使用。因此,一个函数或变量只可能被本模块使用时,其不可能被extern “C”修饰。
二、extern“C”与__cplusplus
#ifdef __cplusplus extern "C" { #endif #ifdef __cplusplus } #endif
_cplusplus标示符用来判断程序是用c还是c++编译程序编译的。当编译c++程序时,这个标示符会被定义,编译c程序时,不会定义。于C++文档的头文件中,上面代码的意思是:如果是C++文件(*.cpp)后缀,则使用extern “C”,在C++项目中应用的非常广泛。
三、C调用C++函数(接口)
1. cpp头文件:animal.h
#ifndef __ANIMAL_H__ //防止被重复包含 #define __ANIMAL_H__ class ANIMAL{ public: ANIMAL(char* ); ~ANIMAL(); char* getname(void); private: char* name; }; #endif // __ANIMAL_H__
2. cpp文件:animal.cpp
#include "animal.h" #include <iostream> #include <string.h> using namespace std; ANIMAL::ANIMAL(char* data)//构造函数 { name = new char[64]; strcpy(name, data); } ANIMAL::~ANIMAL() //析构函数 { if(name) { delete[] name; name = NULL; } } char* ANIMAL::getname(void) { return name; }
3. 中间层cpp头文件:middle.h
#ifndef __MIDDLE_H__ #define __MIDDLE_H__ #ifdef __cplusplus extern "C" { #endif void print(void); #ifdef __cplusplus } #endif #endif
注:middle.h需要包含在.C文件中,因此middle.h中不能包含含有C++关键字(如class)的animal.h.
4. 中间层cpp文件:middle.cpp
#include "middle.h" #include "animal.h" #include <iostream> using namespace std; void print(void) //对外接口 { ANIMAL animal("dog"); char* animal_name = animal.getname(); cout << "animal name is :" << animal_name << endl; }
注:接口函数需要用到C++中的class,因此需要包含animal.h.
5. C文件:test.c
#include "middle.h" int main(int argc, char *argv[]) { print(); return 0; }
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 <stdio.h>
#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代码很简单。
最后更新:2017-04-03 12:56:09
上一篇:
ListView异步加载优化
下一篇:
ListView异步加载优化
Nature:新发现7个临近的类地行星,十年内可研究其生命迹象
Check Mysql Status
如何使用阿里云虚拟主机搭建博客(四)终结篇
iPhone7破解锁屏密码_iPhone7ID密码忘记怎么办
CMU计算机学院院长、谷歌工程VP:未来五年看好AI理解情绪和情感
微软公司第一次全国大笔试将在10月12日进行!
Google 阅读器键盘快捷键
ubuntu安装phpmyadmin
平台之战,开放终将战胜封闭
mysql报错 Access denied for user 'root'@'localhost' (using password: YES)