当前位置:   article > 正文

08 C语言中调用C++的方法(函数),使用回调函数不使用C++动态库_c语言 调用 c++ 回调

c语言 调用 c++ 回调

C语言中调用C++的方法(函数),使用回调函数不使用C++动态库

作者将狼才鲸
创建日期2022-03-31
  • C语言中想调用C++中的方法,或者使用C++类中的数据,有三种方法:
    一是将C++编译成动态库供C语言中调用;
    二是使用Makefile 将C++和C分别用g++和gcc编译成.o,再在链接的时候实现C语言找到C++的方法入口进行调用;
    三是C++调用C语言的一个函数将自己的方法通过回调函数的方式注册进C语言模块,C语言模块自己择机在需要的时候进行调用。

  • 我觉得第三种使用回调函数的方法最好用,也方便单步调试,这里给出用Qt实现的一个例子。

Gitee工程源码地址:t_gui_simple2complex/ source / 005_Qt_with_C_language /
CSDN文章阅读地址:


源码展示

  • mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "cppmodule.h"
#include "c_module.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    // 注册你要在C语言中调用的C++类
    // 该类构造函数中已将方法注册进C语言中
    cppmodule cppm;

    // C语言直接调用C++中的方法
    c_module_process();

    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • cppmodule.cpp
#include <QDebug>
#include "cppmodule.h"
#include "c_module.h"

cppmodule::cppmodule()
{
    data1 = 1;
    data2 = 2;
    data3 = 3;

    // C++类将方法和数据注册进C语言模块,供C语言模块在需要的时候调用
    c_module_init((void *)print1, (void *)print2, data1, data2, data3);
}

int cppmodule::print1()
{
    qDebug("c++ print1");
    return 0;
}

int cppmodule::print2()
{
    qDebug("c++ print2");
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • cppmodule.h
#ifndef CPPMODULE_H
#define CPPMODULE_H

class cppmodule
{
public:
    cppmodule();
    static int print1();
    static int print2();

private:
    int data1;
    int data2;
    int data3;
};

#endif // CPPMODULE_H
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • c_module.c
/**
 * \brief 如果不使用C++动态库,C源码中不能调用C++的内容,只能使用回调函数
 */

#include <stdio.h>

#define NULL ((void *)0)
typedef int (*pfunc)(void);
pfunc cppprint1 = NULL, cppprint2 = NULL;
int cppdata1, cppdata2, cppdata3;

extern int c_module_init(void *func1, void *func2, int data1, int data2, int data3)
{
    if (func1)
        cppprint1 = func1;
    if (func2)
        cppprint2 = func2;

    cppdata1 = data1;
    cppdata2 = data2;
    cppdata3 = data3;

    // 测试g++编译C源码时是否支持GNU C的进阶关键字,如typeof
    printf("C++ callback to C module, data size: %d\n", sizeof(typeof(cppdata1)));

    return 0;
}

int c_module_process()
{
    printf("C++ Class data1~3: %d, %d, %d\n", cppdata1, cppdata2, cppdata3);

    if (cppprint1)
        cppprint1();
    if (cppprint2)
        cppprint2();

    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • c_module.h
#ifndef C_MODULE_H
#define C_MODULE_H

#ifdef __cplusplus
extern "C" {
#endif

// 供C++中调用,将回调函数注册进本C语言模块
extern int c_module_init(void *func1, void *func2, int data1, int data2, int data3);
// C语言模块自己择机执行C++已注册进来的方法
extern int c_module_process();

#ifdef __cplusplus
}
#endif

#endif // C_MODULE_H
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • project.pro
QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++17

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    c_module.c \
    cppmodule.cpp \
    main.cpp \
    mainwindow.cpp

HEADERS += \
    c_module.h \
    cppmodule.h \
    mainwindow.h

FORMS += \
    mainwindow.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • mainwindow.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>800</width>
    <height>600</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget"/>
  <widget class="QMenuBar" name="menubar"/>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

参考网址:
极简式从C调用C++类方法

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/162498
推荐阅读
相关标签
  

闽ICP备14008679号