[MacRuby-devel] Using performRubySelector
Laurent Sansonetti
lsansonetti at apple.com
Wed May 27 18:18:04 PDT 2009
Hi Mike,
On May 26, 2009, at 5:45 PM, Mike Laurence wrote:
> Hello,
>
> I'm trying to get some obj-c code to talk back to my ruby. After
> encountering some "EXC_BAD_ACCESS" messages and scouring the web, I've
> concluded that I'm probably supposed to use performRubySelector
> instead of just expecting selectors to work when overridden by ruby
> subclasses, etc.
>
> What is the preferred way to get this to work? I looked through some
> of Elysium's old code (which used performRubySelector), but I'm having
> trouble wrapping my head around how you're supposed to use the MacRuby
> sharedRuntime to get things to happen. If someone could give me a
> quick example of how to call arbitrary ruby methods, I would highly
> appreciate it.
>
> Of course, if I'm completely off base and there's some other way to
> call ruby code, please let me know!
Calling Ruby from Objective-C can be problematic, depending if you
want to call a pure Ruby method or a Ruby method that overrides an
Objective-C one. If you want to dispatch the method by yourself (and
if it's a Ruby method that overrides a specialized Objective-C
method), you may want to be very careful about the types of the
arguments you are passing to, as well as the return value.
In any case, using performRubySelector: is better because arguments
will be converted from Objective-C objects (id) into the expected
type, and the return value will be converted into an Objective-C
object. Also, performRubySelector: can deal with Ruby methods that
have optional or splat arguments.
$ cat t.m
#import <Foundation/Foundation.h>
#import <MacRuby/MacRuby.h>
@interface Foo : NSObject
@end
@implementation Foo
- (int)aMethodReturningInt
{
return 123;
}
@end
int main(void)
{
[[MacRuby sharedRuntime] evaluateString:@"class X; def foo(x=1,
*a); p x, a; end; end"];
Class k = NSClassFromString(@"X");
id o = [k new];
[o performRubySelector:@selector(foo)];
[o performRubySelector:@selector(foo:) withArguments:@"1", NULL];
[o performRubySelector:@selector(foo:) withArguments:@"1", @"2",
@"3", NULL];
[[MacRuby sharedRuntime] evaluateString:@"class Bar < Foo; def
aMethodReturningInt; 42; end; end"];
k = NSClassFromString(@"Bar");
o = [k new];
NSLog(@"%d", [(Foo *)o aMethodReturningInt]);
NSLog(@"%@", [o
performRubySelector:@selector(aMethodReturningInt)]);
return 0;
}
$ gcc t.m -o t -framework Foundation -framework MacRuby -fobjc-gc
$ ./t
1
[]
"1"
[]
"1"
["2", "3"]
2009-05-27 18:16:36.092 t[11922:10b] 42
2009-05-27 18:16:36.095 t[11922:10b] 42
$
If you still have problems, it would be easier if you could paste some
code, this way I can try to help you more.
HTH,
Laurent
More information about the MacRuby-devel
mailing list