0

我需要从 C 对 OS X 上的 objc_msgSend 进行一些相对简单的调用。这段代码可以正常工作id event_data = objc_msgSend((id) objc_getClass("NSEvent"), sel_registerName("eventWithCGEvent:"), event_ref);,但是,Apple 最近更改了函数签名void objc_msgSend(void);以解决一些问题。普遍的共识是,这应该用函数指针来解决,但是,如果没有一些关于“通过不兼容类型调用的函数”和“如果达到此代码,程序将中止。” 我的新函数指针实现看起来像id event_data = ((id (*)(id, SEL, CGEventRef)) objc_msgSend)((id) objc_getClass("NSEvent"), sel_registerName("eventWithCGEvent:"), event_ref);,但我担心警告。event_ref 变量是定义为的函数参数CGEventRef event_ref。有没有人有做这项工作的想法?

4

1 回答 1

1

你可以试试:

id (*eventWithCGEvent)(Class, SEL, CGEventRef) = (id (*)(Class, SEL, CGEventRef)) objc_msgSend;

这定义了一个用三个参数调用的函数指针eventWithCGEvent:一个接收器(因为它是一个类方法,它是 type Class)、选择器和一个 type 参数CGEventRef

在更多的上下文中,它可能看起来像这样:

#import "objc/message.h"
#import <CoreFoundation/CoreFoundation.h>
#import <CoreGraphics/CoreGraphics.h>


int main(int argc, const char * argv[]) {

    ...

    id (*eventWithCGEvent)(Class, SEL, CGEventRef) = (id (*)(Class, SEL, CGEventRef)) objc_msgSend;


    CGEventRef event_ref = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)42, true);

    Class NSEventClass = objc_getClass("NSEvent");
    SEL eventWithCGEventSelector = sel_registerName("eventWithCGEvent:");
    id event = eventWithCGEvent(NSEventClass, eventWithCGEventSelector, event_ref);
    CFRelease(event_ref);

    ...
    //do sth with event...
    ...

    return 0;
}
于 2020-04-02T21:29:08.863 回答