[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