iOS 开发高手课
戴铭
前滴滴出行技术专家
42934 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 47 讲
用户故事 (1讲)
iOS 开发高手课
15
15
1.0x
00:00/00:00
登录|注册

35 | libffi:动态调用和定义 C 函数

课后作业
小结
如何使用libffi?
libffi 原理分析
如何动态地调用C函数?
libffi: 动态调用和定义 C 函数

该思维导图由 AI 生成,仅供参考

你好,我是戴铭。
在 iOS 开发中,我们可以使用 Runtime 接口动态地调用 Objective-C 方法,但是却无法动态调用 C 的函数。那么,我们怎么才能动态地调用 C 语言函数呢?
C 语言编译后,在可执行文件里会有原函数名信息,我们可以通过函数名字符串来找到函数的地址。现在,我们只要能够通过函数名找到函数地址,就能够实现动态地去调用 C 语言函数。
而在动态链接器中,有一个接口 dlsym() 可以通过函数名字符串拿到函数地址,如果所有 C 函数的参数类型和数量都一样,而且返回类型也一样,那么我们使用 dlsym() 就能实现动态地调用 C 函数。
但是,在实际项目中,函数的参数定义不可能都一样,返回类型也不会都是 void 或者 int 类型。所以, dlsym() 这条路走不通。那么,还有什么办法可以实现动态地调用 C 函数呢?

如何动态地调用 C 函数?

要想动态地调用 C 函数,你需要先了解函数底层是怎么调用的。
高级编程语言的函数在调用时,需要约定好参数的传递顺序、传递方式,栈维护的方式,名字修饰。这种函数调用者和被调用者对函数如何调用的约定,就叫作调用惯例(Calling Convention)。高级语言编译时,会生成遵循调用惯例的代码。
不同 CPU 架构的调用惯例不一样,比如 64 位机器的寄存器多些、传递参数快些,所以参数传递会优先采用寄存器传递,当参数数量超出寄存器数量后才会使用栈传递。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

libffi 是一个用于动态调用和定义 C 函数的库,通过提供底层接口和高级语言接口,使得在不确定参数个数和类型的情况下,能够根据相应规则生成汇编指令的代码来完成函数调用。文章介绍了动态调用 C 函数的原理和实现方式,包括函数调用的约定和调用惯例、libffi 的原理以及使用 libffi 进行函数调用的过程。通过示例代码展示了如何使用 libffi 调用和定义 C 函数,以及如何在运行时动态调用 C 函数。libffi 为不同 CPU 架构下的函数调用提供了一种统一的解决方案,读者可以通过本文了解 libffi 的原理和使用方法,从而在面对语言之间运行时动态调用的问题时,能够更加得心应手。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《iOS 开发高手课》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(11)

  • 最新
  • 精选
  • mersa
    这个库可以用在线上审核么

    作者回复: 可以

    2019-05-30
    2
  • Alex
    能用libffi hook c函数嘛?

    作者回复: 对

    2019-06-18
    1
  • Ant
    为啥少了编译过程也能调用

    作者回复: 文中有说。“就需要先生成动态调用相应寄存器和栈状态的汇编指令。而要达到事...”

    2019-06-01
  • 幻想vs梦想
    首先,为啥要调用c函数,什么场景下我们需要去调用c函数,调用c函数有哪些好处或作用,有点不太懂.
    2020-07-15
    5
  • 开发小能手
    // 有一个问题想要请教老师, 可能与当前文章没有太大的关联. // 在女神(念茜)的博客(iOS安全攻防(二十二):static和被裁的符号表)中提到 /** 如果函数属性为 static ,那么编译时该函数符号就会被解析为local符号。 在发布release程序时(用Xcode打包编译二进制)默认会strip裁掉这些函数符号,无疑给逆向者加大了工作难度。 */ // 但是根据我的测试发现, 实际上并不是女神说的那样.在 iOS 项目中, 一个 C 函数即使是不添加 static 关键字, 在 release 的时候, 也没有具体的符号表. // 这是因为现在的 Xcode (编译器)做了优化了么? @implementation CoderPerson // 发现, 即使是不加 static, 在 release 的时候这个函数符号也没有 // static int coder_func() { int coder_func() { int a = 10; int b = 20; int c = a+b; return c; } - (void)coder_method { int d = coder_func(); NSLog(@"%d", d); } @end 一摸一样的代码、如果放到终端项目中的话,确实是要加上static才会在release的时候被裁减。 感觉是项目的参数配置导致的、但是一直没有找到。
    2019-06-10
    1
    3
  • forping
    struct BlockDescriptor { unsigned long reserved; unsigned long size; void *rest[1]; }; struct Block { void *isa; int flags; int reserved; void *invoke; struct BlockDescriptor *descriptor; }; static void *BlockImpl(id block) { return ((__bridge struct Block *)block)->invoke; } void testFFIBlockCall(){ int(^block)(void) = ^{ NSLog(@"1"); return 2; }; ffi_cif cif; ffi_type *argumentTypes[] = {}; ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 0, &ffi_type_sint32, argumentTypes); void *arguments[] = {}; IMP imp = BlockImpl(block); int retValue; ffi_call(&cif, imp, &retValue, arguments); NSLog(@"ffi_call: %d", retValue); }
    2021-01-26
    1
  • Space
    如何hook C函数?没头绪~
    2021-07-07
  • Master
    没太看明白,好像被调用的函数都是被编译过的啊?
    2020-03-11
  • 三刀流剑客
    可以用libffi动态替换系统+load方法吗
    2019-08-29
  • 林峰峰
    想问下实际应用中,这种动态调用用到了那些方面?
    2019-06-17
收起评论
显示
设置
留言
11
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部