时间:2021-05-19
在工作中,C、C++密不可分,做我们嵌入式方面的,当然更多的是C,但,有时候却少不了C++,而且是C、C++混搭(混合编程)在一起的,比如,RTP视频传输,live555多媒体播放等都是C++下的,他需要调用JRTPLIB库,再比如,我那邮件发送,我也用C++写的,定义了一个Email对象,包含了成员:收发邮件地址,用户名,密码等,以及方法:邮件头、Base64编码和邮件发送这些操作,很好用,所以,很多时候,C++还是蛮不错的。。。。但,*.c与*.cpp文件混搭在一起,不是那么的简单,知识总是:用时方恨少啊!!!现在,我们就来慢慢的了解吧。
一、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 plus plus)即"C++",用于C++文档的头文件中,上面代码的意思是:如果是C++文件(*.cpp)后缀,则使用extern “C”,在C++项目中应用的非常广泛。即使用gcc编译器编译,函数名为C类型如_foo。个人认为,搞懂了这两个关键字,尤其是理解extern "C"(再次强调,不为过,呵呵),接下来的混合编程也就差不多了,哈哈哈。。。。
三、C调用C++函数(接口)
1.设计程序,共四个文件
animal.cppanimal.h main.c Makefile
1.1 animal.h
[root@localhost CC++]#cat animal.h
#ifndef __ANIMAL_H__//防止被重复包含
#define __ANIMAL_H__
#ifdef __cplusplus
extern "C" {
#endif
classANIMAL{
public:
ANIMAL(char* );
~ANIMAL();
char* getname(void);
private:
char* name;
};
void print(void);
#ifdef __cplusplus
}
#endif
#endif // __ANIMAL_H__
1.2 animal.cpp:C++文件
[root@localhost CC++]#cat animal.cpp
#include "animal.h"
#include <iostream>
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;
}
voidprint(void)//对外接口,而且必须有一个非类中方法,才能被C调用
{
ANIMAL animal("dog");
char* animal_name = animal.getname();
cout << "animal name is :" << animal_name << endl;
}
1.3 main.c:C文件
[root@localhost CC++]#cat main.c
int main(void)
{print();
return 0;
}
1.4 Makefile
[root@localhost CC++]#cat Makefile
main:main.c animal.o
gcc-lstdc++main.c animal.o -o main
animal.o:animal.h
g++ -c animal.cpp
.PHONY : clean
clean:
-rm animal.o main
2.测试
2.1生成可执行程序main
[root@localhost CC++]#make
g++ -c animal.cpp
gcc -lstdc++ main.c animal.o -o main
2.2运行可执行程序main
[root@localhost CC++]#./main
animal name is :dog
四、C++调用C函数
应该这个比较简单,我就不多写了,就直接写代码。
共有三个文件:1.h1.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代码很简单,但C调用C++接口可把我给累坏了,苦啊。就是这个gcc后面跟的-lstdc++害的,出现undefined reference to `__gxx_personality_v0'这个错误。是因为你用gcc编译.cpp文件(animal.cpp).按系统默认.cpp文件是c++的文件格式。当然,混搭时,我还遇到了其他的一些问题,都是一些小问题,如果上面解释的还不足以让你解决C\C++混合编程的问题,可以联系我哦.
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
扩展阅读c#基础系列1---深入理解值类型和引用类型c#基础系列2---深入理解String引言在上篇文章深入理解值类型和引用类型的时候,有的小伙伴就推荐说一说
前言本文主要给大家介绍了关于C/C++混合编程extern“C”使用的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。首先要明白:C+
首先,不同语言交互,我们一般把这种编程方式称为混合编程。开发中为什么要多语言混合使用,只用c++不行吗?答案是因为脚本语言语法糖多使用方便、沙盒式安全机制使系统
本文实例讲解了C++中基类和派生类之间的转换。对于深入理解C++面向对象程序设计有一定的帮助作用。此处需要注意:本文实例讲解内容的前提是派生类继承基类的方式是公
当你涉及到C/C++的核心编程的时候,你会无止境地与内存管理打交道。这些往往会使人受尽折磨。所以如果你想深入C/C++编程,你必须静下心来,好好苦一番。现在我们