2012-08-02 75 views
4

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

#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仍然工作,如果这种结构是“不可用”?

回答

6

我只是把在objc运行时头很好看,发现是什么问题,以及如何解决它:)

所以,如果你看一下这个文件,它包含的透明定义的区域结构,你会发现它在体内:

#if !__OBJC2__ 

... 

#endif 

,因为这是规定,这意味着,我们指的是结构实际上是在前置声明和不透明的(因而不完整)。

我们必须做的,而不是为使用提供用于访问这些成员的功能:

IMP method_getImplementation(Method method); 
SEL method_getName(Method method); 
void method_getReturnType(Method method, char *dst, size_t dst_len); 

等等

你可以看到访问方法在Runtime Reference Guide完整列表和很多其他的好东西。

希望它有帮助!

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; 
} 
+0

只是为了阐明,不透明意味着结构是在实现文件中定义的,而不是头文件,是正确的? – 2012-08-02 05:53:52

+1

在c struct的情况下,opaque意味着该名称存在于您使用句柄/指针的实例中,但其内容/字段对您(客户端)隐藏。这就像'CFStringRef',你不能访问这些字段,但你可以在CFString API中使用它。该句柄后面的内存可能是一个形式化的结构,或者它可能是一个C++类型,或者实际上是一个由实现定义的任意内存blob(并且可能在不同版本之间有所不同)。你不能“看到”一个不透明的对象/类型/实例。 – justin 2012-08-02 06:03:52

+1

@JohnCorbett另请参阅:http://en.wikipedia.org/wiki/Opaque_data_type – justin 2012-08-02 06:04:59