Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >iOS runtime通过selector获取IMP地址

iOS runtime通过selector获取IMP地址

作者头像
用户6094182
发布于 2019-08-23 09:56:36
发布于 2019-08-23 09:56:36
1.8K00
代码可运行
举报
文章被收录于专栏:joealzhoujoealzhou
运行总次数:0
代码可运行

iOS runtime通过selector获取IMP地址

获取IMP地址有两种方法:

  • class_getMethodImplementation
  • (class_getInstanceMethod | class_getClassMethod) --> method_getImplementation

下面请看?(代码用swift在playground上完成)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//在swift中获取类名,需要类所在文件名.类名这样拼接。playground中bundleVersion就当做文件名
class Playground : NSObject {
    static var bundleVersion: String {
        let s = self.description().replacingOccurrences(of: ".Playground", with: "")
        return s
    }
}

class Person: NSObject {
    override init() {
        super.init()
        debugPrint("==============class_getMethodImplementation====================")
        getIMPFrom(sel: #selector(instanceFunc))
        getIMPFrom(sel: #selector(Person.classFunc))
        debugPrint("==============method_getImplementation====================")
        getIMPOfMethodFrom(sel: #selector(instanceFunc))
        getIMPOfMethodFrom(sel: #selector(Person.classFunc))
        debugPrint("==============================================================")
        getInstanceIMPFrom(sel: #selector(instanceFunc))
        getClassIMPFrom(sel: #selector(Person.classFunc))
    }
    
    @objc func instanceFunc() {
        debugPrint("instance func")
    }
    
    @objc class func classFunc() {
        debugPrint("class func")
    }
}
//在playground中创建一个Person对象
let p = Person()

一、使用class_getMethodImplementation获取IMP

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/// 第一种方式获取IMP: class_getMethodImplementation
    func getIMPFrom(sel: Selector) {
        let clsName = "\(Playground.bundleVersion).Person"
        let instanceCls = objc_getClass(clsName)
        let instanceImp = class_getMethodImplementation(instanceCls as? AnyClass, sel)
        
        let classCls = objc_getMetaClass(clsName)
        let classImp = class_getMethodImplementation(classCls as? AnyClass, sel)
        
        debugPrint(instanceImp!, classImp!)
    }
"==============class_getMethodImplementation===================="
0x000000011defad20 0x0000000105f4da00
0x0000000105f4da00 0x000000011defaeb0

使用class_getMethodImplementation分别获取实例方法、类方法的IMP。打印出来有两个相同的地址0x0000000105f4da00,这是在调用class_getMethodImplementation时无法找到对应的实现方法。(你可以执行多次都会发现这两个地址虽然会变但都会相同)

二、(class_getInstanceMethod | class_getClassMethod) --> method_getImplementation

使用这种方式获取IMP,先通过class_getInstanceMethod获取实例方法method或者通过class_getClassMethod获取类方法method,再调用method_getImplementation方法获取IMP。通过打印分析:传入selector为实例方法时,会找不到对应的类方法实现。同理传入selector为类方法时,也会找不到对应的实例方法实现。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/// 第二种方式获取IMP:先获取method在获取IMP
    func getIMPOfMethodFrom(sel: Selector) {
        let clsName = "\(Playground.bundleVersion).Person"
        let cls = objc_getClass(clsName)
        if let instanceMethod = class_getInstanceMethod(cls as? AnyClass, sel) {
            let instanceImp = method_getImplementation(instanceMethod)
            debugPrint("instanceIMP: \(instanceImp)")
        } else {
            debugPrint("instanceIMP nil")
        }
        
        let mataCls = objc_getMetaClass(clsName)
        if let classMethod = class_getClassMethod(mataCls as? AnyClass, sel) {
            let classImp = method_getImplementation(classMethod)
            debugPrint("classIMP: \(classImp)")
        } else {
            debugPrint("classIMP nil")
        }
    }
"==============method_getImplementation===================="
"instanceIMP: 0x0000000125bc1d20"
"classIMP nil"
"instanceIMP nil"
"classIMP: 0x0000000125bc1eb0"

三、Tips

通过objc_getMetaClass获取的class是无法找到实例方法的实现的。然而使用objc_getClass获取的class能找到类方法的实现。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/// 使用getMetaClass获取实例方法IMP
    func getInstanceIMPFrom(sel: Selector) {
        let clsName = "\(Playground.bundleVersion).Person"
        let cls = objc_getMetaClass(clsName)
        if let method = class_getInstanceMethod(cls as? AnyClass, sel) {
            let instanceIMP = method_getImplementation(method)
            debugPrint("instanceIMP: \(instanceIMP)")
        } else {
            debugPrint("getMetaClass 无法获取实例方法")
        }
    }
    
    /// 使用getClass获取类方法
    func getClassIMPFrom(sel: Selector) {
        let clsName = "\(Playground.bundleVersion).Person"
        let cls = objc_getClass(clsName)
        if let method = class_getClassMethod(cls as? AnyClass, sel) {
            let classIMP = method_getImplementation(method)
            debugPrint("classIMP: \(classIMP)-------getClass 可以获取类方法")
        } else {
            debugPrint("getClass 无法获取类方法")
        }
    }
"=============================================================="
"getMetaClass 无法获取实例方法"
"classIMP: 0x0000000125bc1eb0-------getClass 可以获取类方法"
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019.04.08 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
RGB源数据操作:图片顺时针90°旋转
gcc 版本 4.4.6 20120305 (Red Hat 4.4.6-4) (GCC)
DS小龙哥
2022/01/12
8910
RGB源数据操作:图片顺时针90°旋转
C/C++ BeaEngine 反汇编引擎
反汇编引擎有很多,这个引擎没有Dll,是纯静态链接库,适合r3-r0环境,你可以将其编译为DLL文件,驱动强制注入到游戏进程中,让其快速反汇编,读取出反汇编代码并保存为txt文本,本地分析。
王瑞MVP
2022/12/28
6630
C/C++ BeaEngine 反汇编引擎
【C++】开源:基于cjson库的json数据处理
项目Github地址:https://github.com/DaveGamble/cJSON
DevFrank
2024/07/24
2190
【C++】开源:基于cjson库的json数据处理
【c语言】详解文件操作(二)
fgetc为字符输入函数,fputc为字符输出函数,适用所以输入流和输出流 函数原型:
用户11029269
2024/03/19
1440
【c语言】详解文件操作(二)
C语言文件操作
相关视频——C语言精华——C语言文件操作,文件打开、关闭、读取、定位如何操作?为你逐一讲解文件操作标准库函数_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili
半生瓜的blog
2023/05/12
2.2K0
C语言文件操作
JSON格式校验类
/** * JSON 校验字符串格式是否为合法的 JSON */ public class JsonValidator { private static CharacterIterator it; private static char c; private static int col; public JsonValidator(){ } /** * 验证一个字符串是否是合法的JSON串 * * @param jsonStr
Dream城堡
2022/01/07
1.1K0
文件操作(二、scanf/fscanf/sscanf​与printf/fprintf/sprintf​、fseek与ftell与rewind、feof)
被错误使用的 feof ​ 牢记:在文件读取过程中,不能用feof函数的返回值直接来判断文件的是否结束。​ feof 的作用是:当文件读取结束的时候,判断是读取结束的原因是否是:遇到文件尾结束。
走在努力路上的自己
2024/01/26
1810
文件操作(二、scanf/fscanf/sscanf​与printf/fprintf/sprintf​、fseek与ftell与rewind、feof)
提取bmp图片的颜色信息,可直接framebuffer显示(c版本与python版本)
稍微了解了下linux的framebuffer,这是一种很简单的显示接口,直接写入像素信息即可
zqb_all
2019/12/27
1.7K0
C++ 分区、文件夹大小获取、文件数据操作demo示例
My Table 1. 获取分区大小和可用空间 2. 获取文件夹大小 3. 删除路径文件 4. 文件行读取即字符串内容比较 5. 传输百分比计算 6. char字符数组打印 7. 读取buffer字符串 8. bin二进制文件读取操作 Android C++模块有时候需要对文件系统进行操作,比如获取某个分区的大小、可用空间,获取某个路径文件夹的大小,文件内容读取及字符串比较、文件大小读取等demo代码示例 1. 获取分区大小和可用空间 //方式3:使用statfs (头文件#include <sys
wizzie
2022/09/28
1.8K0
5.1 C/C++ 使用文件与指针
C/C++语言是一种通用的编程语言,具有高效、灵活和可移植等特点。C语言主要用于系统编程,如操作系统、编译器、数据库等;C语言是C语言的扩展,增加了面向对象编程的特性,适用于大型软件系统、图形用户界面、嵌入式系统等。C/C++语言具有很高的效率和控制能力,但也需要开发人员自行管理内存等底层资源,对于初学者来说可能会有一定的难度。
王瑞MVP
2023/10/10
2660
5.1 C/C++ 使用文件与指针
pcap文件格式及文件解析[通俗易懂]
文件头结构体 sturct pcap_file_header { DWORD magic; DWORD version_major; DWORD version_minor; DWORD thiszone; DWORD sigfigs; DWORD snaplen; DWORD linktype; } 说明: 1、标识位:32位的,这个标识位的值是16进制的 0xa1b2c3d4。 a 32-bit magic number ,The magic number has the value hex a1b2c3d4. 2、主版本号:16位, 默认值为0x2。 a 16-bit major version number,The major version number should have the value 2. 3、副版本号:16位,默认值为0x04。 a 16-bit minor version number,The minor version number should have the value 4. 4、区域时间:32位,实际上该值并未使用,因此可以将该位设置为0。 a 32-bit time zone offset field that actually not used, so you can (and probably should) just make it 0; 5、精确时间戳:32位,实际上该值并未使用,因此可以将该值设置为0。 a 32-bit time stamp accuracy field tha not actually used,so you can (and probably should) just make it 0; 6、数据包最大长度:32位,该值设置所抓获的数据包的最大长度,如果所有数据包都要抓获,将该值设置为65535;例如:想获取数据包的前64字节,可将该值设置为64。 a 32-bit snapshot length” field;The snapshot length field should be the maximum number of bytes perpacket that will be captured. If the entire packet is captured, make it 65535; if you only capture, for example, the first 64 bytes of the packet, make it 64. 7、链路层类型:32位, 数据包的链路层包头决定了链路层的类型。 a 32-bit link layer type field.The link-layer type depends on the type of link-layer header that the packets in the capture file have: 以下是数据值与链路层类型的对应表 0 BSD loopback devices, except for later OpenBSD 1 Ethernet, and Linux loopback devices 以太网类型,大多数的数据包为这种类型。 6 802.5 Token Ring 7 ARCnet 8 SLIP 9 PPP 10 FDDI 100 LLC/SNAP-encapsulated ATM 101 raw IP, with no link 102 BSD/OS SLIP 103 BSD/OS PPP 104 Cisco HDLC 105 802.11 108 later OpenBSD loopback devices (with the AF_value in network byte order) 113 special Linux cooked capture 114 LocalTalk
全栈程序员站长
2022/09/20
9.9K0
熬夜整理的万字C/C++总结(五),值得收藏
文件在今天的计算机系统中作用是很重要的。文件用来存放程序、文档、数据、表格、图片和其他很多种类的信息。作为一名程序员,您必须编程来创建、写入和读取文件。编写程序从文件读取信息或者将结果写入文件是一种经常性的需求。C提供了强大的和文件进行通信的方法。使用这种方法我们可以在程序中打开文件,然后使用专门的 I/O 函数读取文件或者写入文件。
C语言与CPP编程
2021/08/03
9700
TIFF文件切割_tif文件分割
TIFF文件由于可以存储多种形式的数据类型,也可以存储大量的数据,故其体积比较大,如果我们想截取其中的一部分图片数据,如下图:
全栈程序员站长
2022/11/17
1.6K0
TIFF文件切割_tif文件分割
流动的代码:文件流畅读写的艺术(三)
scanf、fscanf 和 sscanf 是 C 语言中用于输入操作的函数,特别是用于格式化输入。它们属于标准输入/输出库,用于按照指定格式从不同来源读取数据。 以下是它们的基本详情和区别:
用户11029103
2024/03/19
1730
流动的代码:文件流畅读写的艺术(三)
C/C++ 文件与指针操作笔记
实现结构块读写: 在定义结构块的时候,不应使用指针变量,因为指正无法被转储到文件中.
王瑞MVP
2022/12/28
8320
网络基础『 序列化与反序列化』
本文将介绍如何使用C++实现简单的服务器和客户端通信,并重点讲解序列化与反序列化的概念和实现。这篇文章将深入探究数据在网络传输中的转换过程,以及如何在C++中应用这些技术
北 海
2024/05/25
2031
网络基础『 序列化与反序列化』
RGB源数据操作:图片顺时针180°镜像、顺时针180°旋转
一、BMP图片顺时针180°镜像 1.1 原图片 image.png 1.2 编译运行过程 [wbyq@wbyq linux_c]$ gcc app.c [wbyq@wbyq linux_c]$ ls 1.bmp 1.c 2.c 666.bmp 888.bmp a.out app.c test.c [wbyq@wbyq linux_c]$ ./a.out 传入的参数格式: ./a.out <原图片的名称> <新图片的名称> [wbyq@wbyq linux_c]$ ./a.out 888
DS小龙哥
2022/01/12
7780
RGB源数据操作:图片顺时针180°镜像、顺时针180°旋转
cJSON基础介绍与代码测试
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。JSON 使用 Javascript语法来描述数据对象,但是 JSON 仍然独立于语言和平台。
xxpcb
2021/04/26
9960
cJSON基础介绍与代码测试
win32 tcp文件传输客户端
#include<stdio.h> #include <stdlib.h> #include <winsock2.h> #include <string.h> #pragma comment(lib,"ws2_32.lib") #define PORT 9999 #define IPADDR "127.0.0.1" #define BACKLOG 20 #define FILENAME 200 #define LENGTH 200 #define BUFFERSIZE 1024 struct F
流川疯
2019/01/18
1.3K0
结构体存入文件并且取出
首先定义结构体 struct student_type { char name[10]; int num; int age; } stud;  将结构体写入 void save() { FILE *fp; int i; if((fp=fopen("stu_list","a+"))==NULL) { printf("canot open the file."); exit(0); } if(fwrite(
cloudskyme
2018/03/20
1K0
相关推荐
RGB源数据操作:图片顺时针90°旋转
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验