C语言调用C++类成员函数讲解和实例

发布时间 2023-11-26 23:27:59作者: MaxBruce

原文:https://blog.csdn.net/LxXlc468hW35lZn5/article/details/125701007

1、问题成因

C语言与C++调用问题原因主要在于C编译器和C++编译器的不同。C是过程式语言,C编译器编译后,函数在符号库中就是函数名,没有其他任何附加信息。而C++是对象式语言,支持函数重载,C++编译器编译后,在符号库中的名字包含了函数名、函数参数类型和函数返回类型等。因此,当两者混合编译时,会相互找不到对象。

2、反汇编证明

我们通过反汇编来证明上述问题,请看下面的例子:

  1.  
    #include "stdio.h"
  2.  
     
  3.  
     
  4.  
    int funP(int a)
  5.  
    {
  6.  
    return 0;
  7.  
    }
  8.  
     
  9.  
     
  10.  
    int main()
  11.  
    {
  12.  
    int a = 0,ret;
  13.  
    ret = funP(a);
  14.  
    return 0;
  15.  
    }

对这一段小程序test.c,我们分别使用gcc和g++两种工具进行编译:

  1.  
    gcc test.c -o testc
  2.  
    g++ test.c -o test+

对可执行程序进行反汇编

d1e59ae2e4fb974830cbb38d842676f2.png

可以看到gcc编译的testc反汇编出来函数名为就是funP,而g++编译的test+反汇编出来函数名为_Z4funPi,带上了返回类型和函数参数类型。两者的不一致导致C与C++相互调用无法找到对应函数。

在C和C++混合编程中,常见的是C++调用C,这种是比较简单的,一个extern “C”{}即可解决问题。而C调用C++则是使用相对较少的,我们通过一个实例来说明C如何调用C++类成员函数。

3、C++程序

3.1、add.h

  1.  
    #ifndef ADD_H
  2.  
    #define ADD_H
  3.  
     
  4.  
     
  5.  
    class addCode
  6.  
    {
  7.  
    public:
  8.  
    addCode();
  9.  
    ~addCode();
  10.  
     
  11.  
     
  12.  
    void setNum(int a);
  13.  
    int getNum();
  14.  
    private:
  15.  
    int m_a;
  16.  
    };
  17.  
     
  18.  
     
  19.  
    #endif

3.2、add.cpp

  1.  
    #include <stdio.h>
  2.  
    #include "add.h"
  3.  
     
  4.  
     
  5.  
    addCode::addCode()
  6.  
    {
  7.  
    m_a = 0;
  8.  
    }
  9.  
     
  10.  
     
  11.  
    addCode::~addCode()
  12.  
    {
  13.  
    }
  14.  
     
  15.  
     
  16.  
    void addCode::setNum(int a)
  17.  
    {
  18.  
    a++;
  19.  
    printf("c++ a = %d\n",a);
  20.  
    m_a = a;
  21.  
    }
  22.  
     
  23.  
     
  24.  
    int addCode::getNum()
  25.  
    {
  26.  
    return m_a;
  27.  
    }

4、中间封装程序

通过中间封装程序,实现C与C++之间的转换,中间封装头文件提供给C和C++程序来调用。

4.1、myadd.h

extern “C”{ } 告诉C++编译器以C的规则来链接函数,以便C编译器之后在对象文件中找到正确的符号。#ifdef _ucplusplus 是因为C编译器不知道关键字extern。

  1.  
    #ifndef MYADD_H
  2.  
    #define MYADD_H
  3.  
     
  4.  
     
  5.  
    #ifdef __cplusplus
  6.  
    extern "C"{
  7.  
    #endif
  8.  
     
  9.  
     
  10.  
    typedef struct addCode addCode;
  11.  
    addCode* newAddCode();
  12.  
    void interSetNum(addCode *v,int a);
  13.  
    int interGetNum(addCode *v);
  14.  
     
  15.  
     
  16.  
    #ifdef __cplusplus
  17.  
    }
  18.  
    #endif
  19.  
    #endif

4.2、myadd.cpp

  1.  
    #include "add.h"
  2.  
    #include "myadd.h"
  3.  
     
  4.  
     
  5.  
    extern "C"{
  6.  
    addCode* newAddCode(){
  7.  
    return new addCode();
  8.  
    }
  9.  
     
  10.  
     
  11.  
    void interSetNum(addCode *v,int a)
  12.  
    {
  13.  
    v->setNum(a);
  14.  
    }
  15.  
     
  16.  
     
  17.  
    int interGetNum(addCode *v)
  18.  
    {
  19.  
    return v->getNum();
  20.  
    }
  21.  
    }

5、C语言主程序 main.c

  1.  
    #include <stdio.h>
  2.  
    #include "myadd.h"
  3.  
     
  4.  
     
  5.  
    int main(void)
  6.  
    {
  7.  
    int a = 1;
  8.  
     
  9.  
     
  10.  
    struct addCode* v = newAddCode();
  11.  
    //传递参数给C++
  12.  
    interSetNum(v,a);
  13.  
    printf("main a = %d\n",a);
  14.  
     
  15.  
     
  16.  
    //获取C++中参数值
  17.  
    a = interGetNum(v);
  18.  
    printf("main get a = %d\n",a);
  19.  
     
  20.  
     
  21.  
    return 0;
  22.  
    }

6、编译执行

为了体验过程,我们不再编写makefile,依次使用如下命令行进行编译:

  1.  
    g++ -c add.cpp -o add.o
  2.  
    g++ -c myadd.cpp -o myadd.o
  3.  
    gcc -c main.c -o main.o
  4.  
    g++ add.o myadd.o main.o -o test

编译完成,执行程序,结果如下:

84d52cbb0373705f1564710d45ed0802.png

通过上述例子,我们实现了C对C++的调用,大家可以参考。

*声明:本文于网络整理,版权归原作者所有,如来源信息有误或侵犯权益,请联系我们删除或授权事宜。

c38c426d1f345af02a573d60660c26b5.png

e920c875729e41730d15186c4fda1041.gif