当前位置: 首页 > news >正文

从 Android 回调到 C 接口:函数指针 + void* self 的一次彻底理解

一、为什么学 C 回调会觉得“抽象”?

很多 Android / Java 开发者在第一次接触 C 回调时,都会被下面这种代码劝退:

typedef struct { void (*open)(void* self); void (*close)(void* self); } Ops;

看起来既不像函数,也不像类,更不像接口。

但当我真正理解它之后,才发现:

这套写法,本质上和 Android 的接口回调是完全一致的,只是语法层面更底层。

二、从 Android 的 setOnClickListener 说起

在 Android 中,我们非常熟悉这种写法:

button.setOnClickListener(listener);

这里发生了三件事:

  1. listener是一个对象实例

  2. 它实现了OnClickListener接口

  3. 系统在合适的时机回调:

listener.onClick(view);

关键点在于:

  • 系统并不关心 listener 的具体类型

  • 只关心:你有没有实现规定的方法

三、C 语言里没有接口,那怎么办?

C 语言没有:

  • class
  • interface
  • this

但系统级代码同样需要:

  • 回调
  • 解耦
  • 多态

于是 C 选择了一种“手工实现接口”的方式:

struct + 函数指针

四、Ops:C 里的“接口定义”

typedef struct { void (*open)(void* self); void (*close)(void* self); } Ops;

这段代码不是在实现逻辑,而是在做一件事:

定义一组能力约定(接口)

可以直接在脑子里翻译成 Java:

interface Ops { void open(); void close(); }

区别只有一个:

  • Java 有隐式this
  • C 需要显式传self

五、void* self 是什么?

void* self的本质是:

C 版的 this / Context / 上下文对象

因为 C 没有对象模型,所以:

  • 谁在调用

  • 状态在哪里

都必须由调用方手动传入

void file_open(void* self) { File* f = (File*)self; printf("%d\n", f->fd); }

这和 Java 里的:

void open() { System.out.println(this.fd); }

在“角色”上是完全等价的。

六、接口是怎么“绑定实现”的?

很多人会问:

file_open为什么会成为open的实现?

答案不在函数名,而在赋值

Ops file_ops = { .open = file_open, .close = file_close };

这一刻发生了绑定:

  • file_ops.open指向file_open

  • file_ops.close指向file_close

之后的调用:

file_ops.open(&f);

等价于:

file_open(&f);

七、file_ops 是什么角色?

可以非常准确地说:

file_ops是一个“接口实例 / 方法表 / 回调对象”

它就像 Android 里的:

OnClickListener listener = new MyClickListener();

只不过在 C 里:

  • 方法表(Ops)

  • 对象实例(self)

被拆开保存。

八、一句话总结构成完整模型

**C 的接口回调 = struct(接口定义)

  • 函数指针(方法)

  • void* self(this / Context)**

这并不是“奇怪的 C 写法”,而是:

在没有语言级支持的情况下,手工实现的面向对象与接口机制。

九、写在最后

当我把 C 的这套回调模型和 Android 的接口机制对齐之后,才真正意识到:

语言不同,但工程思想是完全相通的。

http://www.gsyq.cn/news/122621.html

相关文章:

  • 18、Linux 后台办公基础架构的开源解决方案
  • 【零信任架构落地难点】:政务环境中Agent动态权限控制核心技术
  • 终极Mac菜单栏整理指南:用Dozer隐藏图标打造清爽桌面
  • Java对象差异对比终极指南:如何快速实现对象变化追踪
  • 还在凭经验施肥?AI Agent已实现毫米级精准投喂,产量提升超25%!
  • 广州 大模型备案与算法备案补贴政策解析
  • Charticulator图表定制实战指南:3步打造专业级数据可视化
  • 中国辅助驾驶“新竞赛”打响,高智价比AI芯片如何定义新标杆?
  • 从78%降至3%!全网最实用的论文免费降aigc干货教程(附降AI工具合集) - 殷念写论文
  • 羊皮手套厂家哪家好?2025真皮手套厂家实力排行榜 - 栗子测评
  • 2025上海全屋定制家具工厂权威排行 - 栗子测评
  • 丝苗米推荐:超500万用户力荐的口碑爆款 - 品牌测评家
  • DanmakuFactory弹幕转换:3分钟掌握跨平台弹幕处理技巧
  • 2025全国优质电加热手套厂家实力盘点 - 栗子测评
  • 校园照明问题多,关乎学生视力与学习效率,亟待改善
  • 30、日期处理脚本与Windows 10上Bash安装指南
  • 46、Linux 共享对象与内存问题调试指南
  • HslControls.dll:工业级上位机软件开发的终极控件库
  • 紧急预警:错过生物信息Agent将落后5年!序列分析智能化转型已全面启动
  • 告别 Router Replay:利用 Online IcePop 解决 MoE 模型 RL 训练的不稳定性
  • Unable to create converter for xxx.NetworkResponse<Auth> for method AuthService
  • 3、数据科学命令行入门指南
  • 【打靶日记】HackMyVm 之 Light
  • 失业了一年多后, 有了一个特殊的契机, 远程工作到现在一个月了, 有很多感触想聊一下.在家工作有想象中那么爽吗?爽, 但一些情况与想象中的并不一样.不用上下班真的节约时间吗?真的, 而且节约的
  • 4大核心优势带你玩转PrusaSlicer:专业3D打印切片完全指南
  • 1218 年全国 IX 卷语文《追忆》真题解析
  • NSMusicS容器化部署终极指南:从零构建个人音乐流媒体平台
  • 【金融合规 Agent 审计日志全解析】:掌握7大核心日志字段与合规审计实战技巧
  • 5、实用脚本与工具的深入解析
  • Fold Craft Launcher:移动端Minecraft启动器终极指南