You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于函数内传递回调函数的疑问:status_cb与output_cb执行逻辑

关于PPP回调函数的常见疑问解答

首先得澄清一个关键误解:你看到的output_cb和status_cb不是"未传递参数的函数",而是函数指针——我们把函数的地址传给pppos_create,后续由lwIP的PPP栈在合适的时机自动调用这些函数,并传入对应的参数。

先看整理后的示例代码:

回调函数定义与主函数调用

static void status_cb(ppp_pcb *pcb, int err_code, void *ctx) {
    struct netif *pppif = ppp_netif(pcb);
    switch(err_code) {
        case PPPERR_NONE: {
            printf("status_cb: Connected\n");
            printf(" our_ipaddr = %s\r\n", ipaddr_ntoa(&pppif->ip_addr));
            printf(" his_ipaddr = %s\r\n", ipaddr_ntoa(&pppif->gw));
            printf(" netmask = %s\r\n", ipaddr_ntoa(&pppif->netmask));
            break;
        }
        case PPPERR_PARAM: {
            printf("status_cb: Invalid parameter\r\n");
            break;
        }
    }
}

static u32_t output_cb(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx) {
    return HAL_UART_Transmit_IT(&huart1, data, sizeof(data));
}

int main(void) {
    ppp_pcb *ppp;
    struct netif ppp_netif;
    ppp = pppos_create(&ppp_netif, output_cb, status_cb, 0);
}

pppos_create函数定义

ppp_pcb *pppos_create(struct netif *pppif, pppos_output_cb_fn output_cb, ppp_link_status_cb_fn link_status_cb, void *ctx_cb) {
    pppos_pcb *pppos;
    ppp_pcb *ppp;
    pppos = (pppos_pcb *)LWIP_MEMPOOL_ALLOC(PPPOS_PCB);
    if (pppos == NULL) {
        return NULL;
    }
    ppp = ppp_new(pppif, &pppos_callbacks, pppos, link_status_cb, ctx_cb);
    if (ppp == NULL) {
        LWIP_MEMPOOL_FREE(PPPOS_PCB, pppos);
        return NULL;
    }
    memset(pppos, 0, sizeof(pppos_pcb));
    pppos->ppp = ppp;
    pppos->output_cb = output_cb;
    return ppp;
}

问题1:未传入err_code参数时,status_cb会输出什么?

首先要明确:我们不会直接调用status_cb,这个函数是给lwIP的PPP栈用的回调函数。当PPP链路状态发生变化时(比如连接建立、参数错误),lwIP会自动调用status_cb,并传入对应的err_code参数。

如果真的出现err_code未被传入的极端情况(比如底层调用逻辑出错),err_code会是一个随机的垃圾值:

  • 如果这个随机值恰好等于PPPERR_NONE,会输出连接成功的信息及IP地址、网关、子网掩码;
  • 如果等于PPPERR_PARAM,会输出"status_cb: Invalid parameter";
  • 如果是其他值,因为你的switch没有default分支,函数会直接退出,不会输出任何内容。

但在正常的lwIP使用中,这种情况不会发生——PPP栈一定会正确传入err_code,对应不同的链路事件。

问题2:status_cb和output_cb何时、如何被执行?

这两个都是PPP栈的回调函数,执行时机和触发逻辑如下:

1. status_cb(链路状态回调)

  • 执行时机:当PPP链路的状态发生变化时触发,比如:
    • 连接成功建立(PPPERR_NONE);
    • 检测到无效参数(PPPERR_PARAM);
    • 其他链路错误(比如连接断开、认证失败等,你的代码里没处理这些case)。
  • 执行逻辑:
    在pppos_create中,你传入的status_cb被作为link_status_cb参数传给了ppp_new函数。lwIP的PPP核心模块会在链路状态变更时,通过内部的函数调用链,最终触发status_cb执行,并传入对应的ppp_pcb指针、错误码err_code和你传入的ctx(这里是0)。

2. output_cb(数据输出回调)

  • 执行时机:当PPP栈需要向外发送PPP帧数据时触发,比如协商过程中的控制帧、业务数据帧。
  • 执行逻辑:
    pppos_create把你传入的output_cb保存到了pppos->output_cb中,同时指定了&pppos_callbacks作为PPP操作回调集合。当PPP栈需要发送数据时,会调用pppos_callbacks中的发送函数,这个函数内部会调用你提供的output_cb,传入ppp_pcb指针、待发送的数据指针data、数据长度len和ctx,最终通过你实现的UART中断发送函数把数据发出去。

内容的提问来源于stack exchange,提问作者Sarp Engin Daltaban

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:14:19