35 | 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
《iOS 开发高手课》,新⼈⾸单¥59
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(11)
- 最新
- 精选
- mersa这个库可以用在线上审核么
作者回复: 可以
2019-05-302 - Alex能用libffi hook c函数嘛?
作者回复: 对
2019-06-181 - Ant为啥少了编译过程也能调用
作者回复: 文中有说。“就需要先生成动态调用相应寄存器和栈状态的汇编指令。而要达到事...”
2019-06-01 - 幻想vs梦想首先,为啥要调用c函数,什么场景下我们需要去调用c函数,调用c函数有哪些好处或作用,有点不太懂.2020-07-155
- 开发小能手// 有一个问题想要请教老师, 可能与当前文章没有太大的关联. // 在女神(念茜)的博客(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-1013
- forpingstruct 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-261
- Space如何hook C函数?没头绪~2021-07-07
- Master没太看明白,好像被调用的函数都是被编译过的啊?2020-03-11
- 三刀流剑客可以用libffi动态替换系统+load方法吗2019-08-29
- 林峰峰想问下实际应用中,这种动态调用用到了那些方面?2019-06-17
收起评论