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