从imp调用Objective-C方法

时间:2012-08-02 05:26:46

标签: objective-c data-structures methods objective-c-runtime

我正在尝试在运行时获取一个Method,然后使用其数据结构来调用它的实现。只是为了澄清,这是出于学习目的,而不是出于任何实际原因。所以这是我的代码。

#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;
}

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;

然而,当我尝试编译我的代码时,我收到此错误。

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;

有人可以向我解释为什么我的代码在显式声明这个结构时有效,而不是从objc / runtime.h导入它时?它与OBJC2_UNAVAILABLE有什么关系吗?我找不到它的定义,但它是在我的环境中定义的。

编辑:

我运行gcc -E code.m -o out.m以查看OBJC2_UNAVAILABLE被替换为什么,事实证明OBJC2_UNAVAILABLE在我的环境中被定义为__attribute __((不可用))。如果这个结构“不可用”,有人可以解释这意味着什么以及为什么Method仍然有效?

1 个答案:

答案 0 :(得分:3)

其字段先前已定义,但它是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;
}