zoukankan      html  css  js  c++  java
  • c/c++实现混合编程

    在开发中大家经常会使用到c与c++混合编程,这样能够更好的实现功能模块。刚学习了一下c和c++的混合编程,参考了网上的相关知识,在这里留下要点,方便以后进行查阅。

    1、extern关键字

      extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。此外extern也可用来进行链接指定。

      也就是说extern有两个作用,第一个,当它与"C"一起连用时,如: extern "C" void fun(int a, int b);则告诉编译器在编译fun这个函数名时按着C的规则去翻译相应的函数名而不是C++的,C++的规则在翻译这个函数名时会把fun这个名字变得面目 全非,可能是fun@aBc_int_int#%$也可能是别的,这要看编译器的"脾气"了(不同的编译器采用的方法不一样),为什么这么做呢,因为 C++支持函数的重载啊,在这里不去过多的论述这个问题,如果你有兴趣可以去网上搜索,相信你可以得到满意的解释!
        第二,当extern不与"C"在一起修饰变量或函数时,如在头文件中: extern int g_Int; 它的作用就是声明函数或全局变量的作用范围的关键字,其声明的函数和变量可以在本模块活其他模块中使用,记住它是一个声明不是定义!也就是 说B模块(编译单元)要是引用模块(编译单元)A中定义的全局变量或函数时,它只要包含A模块的头文件即可,在编译阶段,模块B虽然找不到该函数或变量, 但它不会报错,它会在连接时从模块A生成的目标代码中找到此函数。

    2、混合编写代码

    常见模型:

    #ifdef __cplusplus
           extern "C" {
           #endif
    
        **********内容
           #ifdef __cplusplus
           }
           #endif
    /***
    宏 __cplusplus C++中会定义 而C中不会定义
    */

    A:c++中调用c程序:

      由于c++基本包含了全部的c,但是由于c++是面向对象编程的语言,能够支持函数的重载,面向对象编程,给编程带来了很多的好处,但是由于这些特性,c++编译器在编译C++程序时,对这些编译后的标识和C中几乎不相同。他们编程以后的标识符不相同,所以在调用的时候,会出现函数没有定义之类的错误。

      例如:

    //header.h
    #ifndef __HEADER
    #define __HEADER
    
    extern void print(char* ch);
    
    #endif
    
    //1.cpp
    #include <iostream>
    extern"C"{
    #include "header.h"
    }
    using namespace std;
    
    
    int main()
    {
        print("yyrrom");
        return 0;
    }
    
    //2.c
    #include <stdio.h>
    #include "header.h"

    void print(char* ch)
    {
        printf("%s ",ch);
    }

    执行

    root@localhost tt]# gcc -c 2.c
    [root@localhost tt]# g++ 1.cpp 2.o -o 1
    [root@localhost tt]# ./1
    yyrrom
    

     这样执行ok,extern"C" 告诉编译器,按照函数原有的方式进行编译。这样在在c调用时能够正确找到函数,-lstdc++表示加载c++动态库。

    B:C中调用c++程序

      在C中调用的C++程序中,C++程序中有可能出现类等等C中没有的特性,出现这样情况,一般方式是采用接口函数的方式来实现对对象的调用。

    例如:

    header.h文件
    #ifndef HEADER
    #define HEADER
    
    #include <string>
    
    using namespace std;
    #ifdef __cplusplus
    extern"C"{
    #endif
    class number
    {
    	public:
    		number();
    		number(int x,string ch);
    		~number();
    		int getage();
    		string getname();
    	private:
    		int age;
    		string name;
    };
    
    void get();
    #ifdef __cplusplus
    }
    #endif
    #endif
    
    //test.cpp文件
    #include <iostream>
    #include <string>
    #include "header.h"
    
    using namespace std;
    
    
    number::number()
    {
    }
    
    number::number(int x,string ch)
    {
        age = x;
        name = ch;
    }
    
    number::~number()
    {
    
    }
    
    int number::getage()
    {
        return age;
    }
    string number::getname()
    {
        return name;
    }
     void get()
    {
        number t(20,"yangyin");
        cout<<"name:"<<t.getname()<<"   age:"<<t.getage()<<endl;
    }
    //main.c
    #include <stdio.h>
    
    int main()
    {
    	get();
    }
    

     编译:makefile文件:

    CC=gcc
    CXX=g++
    main:main.c test.o
    	${CC}  -lstdc++ main.c test.o -o main
    test.o:header.h
    	${CXX} -c test.cpp
    .PHONY:clean
    clean:
    	rm -f *.o main
    

     gcc与g++常见误区

    误区一 :    gcc只能编译c代码,g++只能编译c++代码  
      两者都可以,但是请注意:  
      1.后缀为.c的,gcc把它当作是C程序,而g++当作是c++程序;后缀为.cpp的,两者都会认为是c++程序,注意,虽然c++是c的超集,但是两者对语法的要求是有区别的。C++的语法规则更加严谨一些。  
      2.编译阶段,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,二者等价。
    
  • 相关阅读:
    web前端开发最佳实践--(笔记之JavaScript最佳实践)
    web前端开发最佳实践--(笔记一)
    HTML5及CSS3--freeCodeCamp(笔记一)
    javascript系列--函数(一)
    HTML5本地存储
    分享一些好用的设计网站
    .net面试问题总结
    ife_task10--弹性盒子
    WPF--搭建一个简单的demo
    信息技术文集
  • 原文地址:https://www.cnblogs.com/yyroom/p/3667539.html
Copyright © 2011-2022 走看看