关于嵌入式C&&C++的一些编程问题(四)

这里讨论一下C&&C++的混合编程。主要参考了博文http://blog.csdn.net/skdkjzz/article/details/17073339;其实混合编程的方法在写程序的时候很常用,比如Matlab、Python等于C、C++的混合编程,充分利用不同语言的长处或者要用到的库文件;

在C与C++的混合编程是,主要涉及到extern "c" 和C++文件中_cplusplus;

一、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, inty);该函数被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 plusplus)即"C++",用于C++文档的头文件中,上面代码的意思是:如果是C++文件(*.cpp)后缀,则使用extern“C”,在C++项目中应用的非常广泛。即使用gcc编译器编译,函数名为C类型如_foo。个人认为,搞懂了这两个关键字,尤其是理解extern"C"(再次强调,不为过,呵呵),接下来的混合编程也就差不多了偷笑
 
三、C调用C++函数(接口)
1.设计程序,共四个文件
animal.cpp animal.h main.c Makefile
1.1animal.h
[root@localhostCC++]#catanimal.h
#ifndef__ANIMAL_H__  //防止被重复包含
#define__ANIMAL_H__
#ifdef__cplusplus
extern "C"{
#endif
classANIMAL{
public:
       ANIMAL(char* );
       ~ANIMAL();
       char* getname(void);
private:
       char* name;
};
voidprint(void);
#ifdef__cplusplus
}
#endif
#endif // __ANIMAL_H__
 
1.2animal.cpp:C++文件
[root@localhostCC++]#catanimal.cpp
#include"animal.h"
#include
usingnamespace 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 < }
 
1.3main.c:C文件
[root@localhostCC++]#cat main.c
intmain(void)
{
       print();
       return 0;
}
 
1.4Makefile
[root@localhostCC++]#cat Makefile
main:main.canimal.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@localhostCC++]#make
g++ -c animal.cpp
gcc -lstdc++ main.c animal.o -o main
2.2运行可执行程序main
[root@localhostCC++]#./main
animalname is :dog
 
四、C++调用C函数
应该这个比较简单,我就不多写了,就直接写代码。
共有三个文件:1.h 1.c main.cpp
[root@localhostaa]#cat1.h
#ifndef_1__H_
#define_1__H_
extern voidprint(char* );
#endif
 
[root@localhostaa]#cat1.c
#include
#include"1.h"
voidprint(char* data)
{
       printf("%s\n",  data);
}
 
[root@localhostaa]#catmain.cpp
extern"C"{
#include"1.h"}
intmain(void)
{
       print(“hello,world\n”);
       return 0;
}
 
gcc –c 1.c
g++ main.cpp 1.o
 
gcc编译.cpp文件(animal.cpp).按系统默认.cpp文件是c++的文件格式。

关于gcc与g++:https://www.zhihu.com/question/20940822/answer/69547180

编译阶段,g++会调用gcc,对于c++代码,两者是等价的,但是因为gcc命令不能自动和C++程序使用的库联接,所以通常用g++来完成链接,为了统一起见,干脆编译/链接统统用g++了,这就给人一种错觉,好像cpp程序只能用g++似的。

误区二:gcc不会定义__cplusplus宏,而g++会实际上,这个宏只是标志着编译器将会把代码按C还是C++语法来解释,如上所述,如果后缀为.c,并且采用gcc编译器,则该宏就是未定义的,否则,就是已定义。

误区三:编译只能用gcc,链接只能用g++严格来说,这句话不算错误,但是它混淆了概念,应该这样说:编译可以用gcc/g++,而链接可以用g++或者gcc -lstdc++。因为gcc命令不能自动和C++程序使用的库联接,所以通常使用g++来完成联接。但在编译阶段,g++会自动调用gcc,二者等价。

你可能感兴趣的:(C&&C++嵌入式编程)