[C语言]

单片机回调函数请教:怎样获取其它文件的函数的地址

[复制链接]
405|15
手机看帖
扫描二维码
随时随地手机跟帖
panxiaoyi|  楼主 | 2023-3-27 22:20 | 显示全部楼层 |阅读模式
//interrupt.h 文件,由甲方编写 

#ifndef INTERRUPT_H
#define INTERRUPT_H

void interrupt(void);
void add(void);

#endif
//interrupt.c 文件,由甲方编写 

#include "interrupt.h"

void interrupt(void)
{
        void (*func)();
        func=add;
        func();
        add();
}
//main.c文件,由乙方编写 

#include <stdio.h>
#include <stdlib.h>
#include "interrupt.h"

//==============================

void add(void)
{
        static int test;
        test++;
        printf("test=%d\n",test);
}

//==============================

int main(void)
{
        interrupt();
        return 0;
}

//end
运行结果:
test=1
test=2



使用特权

评论回复

相关帖子

panxiaoyi|  楼主 | 2023-3-27 22:24 | 显示全部楼层
请教:如果甲方不知道乙方的函数名是 add,那么,甲方怎样才能运行乙方的add函数,就是说,甲方怎样获取乙方的add函数的地址?

使用特权

评论回复
panxiaoyi|  楼主 | 2023-3-27 22:40 | 显示全部楼层
本帖最后由 panxiaoyi 于 2023-3-27 22:45 编辑
//函数 interrupt() 是模拟单片机中断运行函数 ,是由甲方编写的底层函数 
//甲方的目的是要在中断里面调用乙方的用户层面的函数
//我现在遇到的问题是:甲方是底层开发,乙方是用户层开发,所以,甲方不知道用户函数名叫add
//所以,如果甲方没有下面两条语句 那么,甲方是怎样去获取乙方的函数的地址呢
  func=add;
  void add(void);
//我看了很多网上的回调函数的例子,这些例子要么是在同一个C文件内完成,要么非常的复杂,看不懂。
//请教,谢谢

使用特权

评论回复
banyai| | 2023-3-28 08:03 | 显示全部楼层
把interrupt()函数写成需要传入函数指针参数就可以啊。

使用特权

评论回复
computer00| | 2023-3-28 09:27 | 显示全部楼层
本帖最后由 computer00 于 2023-3-28 19:57 编辑

可以让甲方给你增加一个注册中断回调函数的接口,等中断发生时,就可以回调到乙方定义的函数了。例如:
/////////////////////////////////// interrupt.c ///////////////////////////////////////
typedef int (*IsrCallbackFuncType)(int id, void *data);

#define CONFIG_MAX_INTS 8
static IsrCallbackFuncType sgIsrCbTab[CONFIG_MAX_INTS];
static void* sgIsrCbData[CONFIG_MAX_INTS];

int registerInterruptCallback(int intId, IsrCallbackFuncType callbackFunc, void *pData) {
    if (intId < 0 || intId >= CONFIG_MAX_INTS) {
        return -1;
    }

    sgIsrCbTab[intId] = callbackFunc;
    sgIsrCbData[intId] = pData;

    return 0;
}

void interrupt(void) {
    int id = 0;

    // do something, eg. id = getIntId();

    if (sgIsrCbTab[id] != 0) {
        int ret = sgIsrCbTab[id](id, sgIsrCbData[id]);
    }

    // do something, eg. clean int flag
}


//////////////////////////////////////////////// main.c ////////////////////////////////////////////
typedef int (*IsrCallbackFuncType)(int id, void *data);
int registerInterruptCallback(int intId, IsrCallbackFuncType callbackFunc, void *pData);

int timerIsrCb(int id, void *data) {
    printf("%s, %d: id = %d, data = '%s'\n", __FUNCTION__, __LINE__, id, (char *)data);
}

void main(void) {
    char buffer[128] = {"Hello LSTM"};
    int ret = registerInterruptCallback(0, timerIsrCb, (void *)buffer);
}

使用特权

评论回复
gyh974| | 2023-3-28 11:55 | 显示全部楼层
这样做有什么好处,为什么要分开两边写,还不能沟通

使用特权

评论回复
ayb_ice| | 2023-3-28 13:01 | 显示全部楼层
一般是建个数组,数组中存放函数地址,数组使用绝对定位就可以了

使用特权

评论回复
timerc| | 2023-3-28 15:25 | 显示全部楼层
正常库一般会有头文件的啊,头文件里面有函数名,库里面是函数实现,调用要看头文件里面的函数调用,不是瞎蒙吧。不同层之间,你要有头文件,不然你怎么知道哪个函数符合要求可以用。。。。乱写一通??

使用特权

评论回复
sanzi666| | 2023-3-28 17:57 | 显示全部楼层
不知道函数名字,怎么把函数指针指向函数入口地址,
除非强制定义地址,然后调用,

使用特权

评论回复
panxiaoyi|  楼主 | 2023-3-29 13:17 | 显示全部楼层
多谢大家,特别是 5楼 computer00,我会好好的学习的,就是不知道能不能看的懂,后面会继续反馈的

使用特权

评论回复
panxiaoyi|  楼主 | 2023-3-29 13:31 | 显示全部楼层
gyh974 发表于 2023-3-28 11:55
这样做有什么好处,为什么要分开两边写,还不能沟通

回复6楼,因为我现在在写小工程,渐渐的发现,工程全局变量真的越少越好,多了就容易引起逻辑混乱,查错困难。后来又发现,硬件底层很多时候需要调用应用层的函数,于是,就学习到了回调函数,现在就卡在这里了。
需要说明的是,我现在写的基本上都是8位机的代码,但是工程很多,需要经常移植,所以,上面的问题就很自然的浮出水面了

使用特权

评论回复
panxiaoyi|  楼主 | 2023-4-2 17:46 | 显示全部楼层
下面是我的理解,如果大家有空,请帮我看看是否正确,谢谢
//interrupt.h 文件,由甲方编写 

#ifndef INTERRUPT_H
#define INTERRUPT_H

void interrupt(void);
void CallBackRegister(void(*func2)());

#endif

//interrupt.c                            //模拟单片机中断文件,由甲方编写

#include "interrupt.h"

static void (*func3)();                  //定义函数指针变量(产生代码,非声明)
              
//==============================

void CallBackRegister(void(*func2)()) {  //定义注册函数,给乙方使用
        func3 = func2;                       //记忆乙方的函数地址,这就是回调函数注册
}

//==============================

void interrupt(void) {
        void (*func)();                      //定义局部函数指针变量
        func = func3;                        //将上面注册进来的地址赋值测试
        func();                              //通过指针,运行被调用的函数
        add();                               //普通方式,直接调用函数
}

//==============================

/*
请教:

1:
请问,这里的甲方是不是(必须)要定义一个本文件的全局函数指针变量 func3
然后,注册函数 CallBackRegister 和 中断函数 interrupt 共用这个变量,
这样甲方才能"知道"和"运行"乙方传进来的函数

2:
我在代码上的注释是否正确,因为它代表了我的理解。谢谢
*/

//main.c                           //main.c 文件,由乙方编写

#include <stdio.h>
#include "interrupt.h"

//==============================

void add(void) {                   //定义被调用的函数,这个函数叫“回调函数”
        static int test;               //测试变量
        test++;                        //变量++
        printf("test=%d\n", test);     //输出显示
}

//==============================

int main(void) {                   //用户(乙方)的主函数
        CallBackRegister(add);         //注册回调函数,就是把add函数的地址告诉甲方
        interrupt();                   //模拟单片机进入中断服务函数
        return 0;
}

//end


使用特权

评论回复
panxiaoyi|  楼主 | 2023-4-2 17:49 | 显示全部楼层
代码截图

微信截图_20230402174820.png

使用特权

评论回复
zwsam| | 2023-12-30 00:08 | 显示全部楼层

使用特权

评论回复
zwsam| | 2023-12-30 00:08 | 显示全部楼层

使用特权

评论回复
zwsam| | 2023-12-30 00:08 | 显示全部楼层

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

47

主题

384

帖子

2

粉丝