2

Objective-C の世界では、次のような単純なアラートボックスを開きたいとします。

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)
4

1 に答える 1

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 ...))

またはそのようなもの。

その時点で、MacRubyまたはRubyCocoaの非常に初歩的な形式を再発明したことになります。

于 2013-06-06T16:49:58.897 に答える