Reputation: 838
Say you want to open a simple alertbox, which in the objective-c universe would be something like:
NSAlert *alert = [[[NSAlert alloc] init] autorelease];
[alert setMessageText:@"Alert."];
[alert beginSheetModalForWindow:window
modalDelegate:self
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:)
contextInfo:nil];
The beginModalForWindow is defined as a selector method. In apples reference guide it's full name is "beginSheetModalForWindow:modalDelegate:didEndSelector:contextInfo:"
It's defined in NSAlert.h as:
- (void)beginSheetModalForWindow:(NSWindow *)window modalDelegate:(id)delegate didEndSelector:(SEL)didEndSelector contextInfo:(void *)contextInfo;
Now the simple question, how to define this method in 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
Fails with:
An exception occurred running ffi-test.rb
Function 'beginSheetModalForWindow' not found in [/System/Library/Frameworks/AppKit.framework/AppKit] (FFI::NotFoundError)
Upvotes: 2
Views: 513
Reputation: 162712
In short, you can't. At least not without a slew of hoop jumping.
attach_function
does what it says; it binds a C function into the Ruby runtime. beginSheetModalForWindow:modalDelegate:didEndSelector:contextInfo:
is not a C function; it is a selector.
What you really want to bind is the implementation of that selector.
But not really.
What you'd really want to bind is objc_msgSend
with a type signature that includes all the arguments to that method. And you'll also need to attach sel_getUid
. Oh, and you'll need to attach objc_lookUpClass
Then you would do something like (pseudo code):
... 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 ...))
Or something like that.
At which point, you've re-invented a very rudimentary form of MacRuby or RubyCocoa.
Upvotes: 3