Joh*_*ett 4 methods objective-c objective-c-runtime data-structures
我试图在运行时获取一个方法,然后使用其数据结构来调用它的实现.只是为了澄清,这是出于学习目的,而不是出于任何实际原因.所以这是我的代码.
#import <Foundation/Foundation.h>
#import <stdio.h>
#import <objc/runtime.h>
@interface Test : NSObject
-(void)method;
@end
@implementation Test
-(void)method {
puts("this is a method");
}
@end
int main(int argc, char *argv[]) {
struct objc_method *t = (struct objc_method*) class_getInstanceMethod([Test class], @selector(method));
Test *ztest = [Test new];
(t->method_imp)(ztest, t->method_name);
[ztest release];
return 0;
}
Run Code Online (Sandbox Code Playgroud)
定义struct objc_method如下(在objc/runtime.h中定义)
typedef struct objc_method *Method;
....
struct objc_method {
SEL method_name OBJC2_UNAVAILABLE;
char *method_types OBJC2_UNAVAILABLE;
IMP method_imp OBJC2_UNAVAILABLE;
} OBJC2_UNAVAILABLE;
Run Code Online (Sandbox Code Playgroud)
但是当我尝试编译我的代码时,我得到了这个错误.
error: dereferencing pointer to incomplete type
但是当我将它添加到我的代码中(显式声明一个objc_method)时,它的工作方式与预期的一样.
struct objc_method {
SEL method_name;
char *method_types;
IMP method_imp;
};
typedef struct objc_method* Method;
Run Code Online (Sandbox Code Playgroud)
有人可以向我解释为什么我的代码在我显式声明这个结构时工作,而不是从objc/runtime.h导入它时?它与OBJC2_UNAVAILABLE有什么关系吗?我找不到它的定义,但它是在我的环境中定义的.
编辑:
我跑去gcc -E code.m -o out.m看看OBJC2_UNAVAILABLE被替换了什么,事实证明在我的环境中OBJC2_UNAVAILABLE被定义为__attribute __((不可用)).有人可以解释这意味着什么,Method如果这个结构"不可用" ,为什么仍然有效?
我只是好好看看objc运行时头,发现问题是什么,以及如何解决它:)
因此,如果您查看包含结构透明定义的文件区域,您将看到它位于以下体内:
#if !__OBJC2__
...
#endif
Run Code Online (Sandbox Code Playgroud)
由于这是IS定义的,这意味着我们所引用的结构实际上是前向声明的和不透明的(因此是不完整的).
我们必须做的是使用为访问这些成员而提供的功能:
IMP method_getImplementation(Method method);
SEL method_getName(Method method);
void method_getReturnType(Method method, char *dst, size_t dst_len);
Run Code Online (Sandbox Code Playgroud)
等等.
您可以在" 运行时参考指南"中查看访问者方法的完整列表以及许多其他好东西.
希望能帮助到你!
它的字段先前已定义,但它在 ObjC-2 中是不透明类型。改用运行时,不要自己定义字段:
int main(int argc, char *argv[]) {
Method t = class_getInstanceMethod([Test class], @selector(method));
Test * ztest = [Test new];
IMP imp = method_getImplementation(t);
typedef void (*fn)(id,SEL);
fn f = (fn)imp;
f(ztest,@selector(method));
[ztest release];
return 0;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3423 次 |
| 最近记录: |