假设您要打开一个简单的警告框,它在objective-c Universe中将类似于:
NSAlert *alert = [[[NSAlert alloc] init] autorelease];
[alert setMessageText:@"Alert."];
[alert beginSheetModalForWindow:window
modalDelegate:self
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:)
contextInfo:nil];
beginModalForWindow被定义为选择器方法。在苹果参考指南中,它的全名是“beginSheetModalForWindow:modalDelegate:didEndSelector:contextInfo:”
它在NSAlert.h中定义为:
- (void)beginSheetModalForWindow:(NSWindow *)window modalDelegate:(id)delegate didEndSelector:(SEL)didEndSelector contextInfo:(void *)contextInfo;
现在这个简单的问题,如何在ruby ffi中定义这个方法?
module AppKit
extend FFI::Library
# Load the Cocoa framework's binary code
ffi_lib '/System/Library/Frameworks/AppKit.framework/AppKit'
attach_function :beginSheetModalForWindow, [:pointer,:pointer,:pointer], :bool
end
失败:
An exception occurred running ffi-test.rb
Function 'beginSheetModalForWindow' not found in [/System/Library/Frameworks/AppKit.framework/AppKit] (FFI::NotFoundError)
答案 0 :(得分:3)
attach_function
按照说法行事;它将 C函数绑定到Ruby运行时。 beginSheetModalForWindow:modalDelegate:didEndSelector:contextInfo:
不是C函数;它是一个选择器。
您真正想要绑定的是该选择器的实现。
但不是真的。
您真正想要绑定的是objc_msgSend
,其类型签名包含该方法的所有参数。而且你还需要附上sel_getUid
。哦,你需要附上objc_lookUpClass
然后你会做类似(伪代码)的事情:
... attach objc_msgSend to msgSend with no arguments and object return type ...
alert = msgSend(msgSend(msgSend(lookupClass("NSAlert"),getUid("alloc")),
getUid("init")), getUid("autorelease"))
... attach objc_msgSend to bs with all the arguments for beginSheetModal....
bs(alert, getUid("beginSheetModalForWindow:modalDelegate:didEndSelector:contextInfo", ... all the arguments ...))
或类似的东西。