• 深入理解C/C++混合编程


    本篇资料问转载,内容是C++和C语言混合编程,但是实际操作中和资料部分内容有所出入,必要地方已经加上注释。

    在工作中,CC++密不可分,做我们嵌入式方面的,当然更多的是C,但,有时候却少不了C++,而且是CC++混搭(混合编程)在一起的,比如,RTP视频传输,live555多媒体播放等都是C++下的,他需要调用JRTPLIB库,再比如,我那邮件发送,我也用C++写的,定义了一个Email对象,包含了成员:收发邮件地址,用户名,密码等,以及方法:邮件头、Base64编码和邮件发送这些操作,很好用,所以,很多时候,C++还是蛮不错的。。。。但,*.c*.cpp文件混搭在一起,不是那么的简单,知识总是:用时方恨少啊!!!现在,我们就来慢慢的了解吧。

    一、extern“C”的作用(最重点)

        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连接交换指定符号extern“C”来解决名字匹配问题。

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

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

    二、extern“C”__cplusplus

    #ifdef __cplusplus
           extern "C" {
           #endif
           #ifdef __cplusplus
           }
           #endif
        CplusplusC plus plus"C++"用于C++文档的头文件中,上面代码的意思是:如果是C++文件(*.cpp)后缀,则使用extern “C”,在C++项目中应用的非常广泛。即使用gcc编译器编译,函数名为C类型如_foo。个人认为,搞懂了这两个关键字,尤其是理解extern "C"(再次强调,不为过,呵呵),接下来的混合编程也就差不多了,哈哈哈。。。。

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

    1.设计程序,共四个文件

    animal.cpp animal.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

    class ANIMAL{
    public:
            ANIMAL(char* );
            ~ANIMAL();
            char* getname(void);
    private:
            char* name;
    };
    void print(void);
    #ifdef __cplusplus
    }
    #endif
    #endif  // __ANIMAL_H__

    1.2 animal.cppC++文件

    [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;
    }
    void print(void) //对外接口,而且必须有一个非类中方法,才能被C调用
    {
            ANIMAL animal("dog");
            char* animal_name = animal.getname();
            cout << "animal name is :" << animal_name << endl;
    }

    1.3 main.cC文件

    [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.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 ",  data);
    }
    [root@localhost aa]#cat main.cpp

    extern "C"{         //本人亲自实验中,用C++程序调用C不加extern "C"编译运行通过,加上反而报错,特在次注释14/04/29
    #include "1.h"}
    int main(void)
    {
            print(“hello,world ”);
            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++的文件格式。当然,混搭时,我还遇到了其他的一些问题,都是一些小问题,如果上面解释的还不足以让你解决CC++混合编程的问题,可以联系我哦.

    //原文的最后一段有些不好理解,意思也就是gcc编译器做连接的时候默认会自动加载一些库文件,但是不包括stdc++这个库,所以用gcc连接C++模块的时候要在命令行显式加载stdc++这个库(-lstdc++)



    原文链接   http://www.jb51.net/article/37386.htm


  • 相关阅读:
    flowableU应用
    公募REITs打新基本
    A股市场人气排名因子
    flowableUI 流程演示
    flowable之监听器分配
    flowable基础二,
    【python股票量化】人气指标AR策略编程实现
    Java使用hutool工具类发送http请求
    一个模拟消息订阅和发布的简单程序
    CAXA基本操作旋转
  • 原文地址:https://www.cnblogs.com/slz-coder150315/p/4376372.html
Copyright © 2020-2023  润新知