Hi Victor,

On Apr 16, 2009, at 4:23 AM, macruby-de...@principia.info wrote:

Hi,

I'm new both to this list and to MacRuby. Let this message serve as an introduction.

I have some questions that have not seen answered either in the docs or in the list archives. I have been known to miss things before, so please kindly point me in the right direction if this is documented somewhere.

I have seen the embedding sample but I stil can't figure out how I can pull out the following:

1. Mix Obj-C and Ruby Classes: ie, from Ruby be able to extend or use Obj-C classes that are lying around in my project. How do I "require" them? When I try to use them, ruby doesn't seem to recognize them (specifically, it recognizes the classes but not their methods)

Normally MacRuby will recognize your Objective-C classes and their methods. If you see the classes from Ruby but not the methods it may be a problem in the way you use MacRuby (or a bug in MacRuby).

Also, keep in mind that calling #methods on an object in Ruby won't show the Objective-C selectors, you need to pass the second parameter as true to show them (this is to keep compatibility with Ruby).

$ cat hello.m
#import <Foundation/Foundation.h>

@interface Foo : NSObject
@end

@implementation Foo

- (void)sayHello:(id)sender
{
    NSLog(@"hey %...@!", sender);
}

@end

// We declare an Init_ method so that we can load this extension from MacRuby
// using #require.
void Init_hello(void) {}

$ gcc hello.m -o hello.bundle -g -framework Foundation -dynamiclib - fobjc-gc -arch i386 -arch x86_64

$ macruby -e "require 'hello'; Foo.new.sayHello('MacRuby')"
2009-04-17 22:44:49.495 macruby[67329:10b] hey MacRuby!

2. The same question, but the other way around: how can I use or extend a class declared in Ruby from Obj-C? The only thing that I can come up with is to declare them with @class, but it didn't work (or I didn't do it properly)

This is also possible, but it requires some runtime calls since Objective-C is more static than Ruby (the problem is that Objective-C declares classes at compilation time but Ruby does it at runtime). Here is a dirty way to do this (note that it uses a deprecated API in the runtime). Another cleaner way would be to subclass the Ruby class dynamically too, by creating the class programmatically right after loading the Ruby expression.

$ cat hello2.m #import <Foundation/Foundation.h>
#import <MacRuby/MacRuby.h>

@interface NSObject (FooInterface)
- (id)foo;
@end

@interface ObjCFoo : NSObject
@end

@implementation ObjCFoo

- (id)foo
{
    NSLog(@"objc_foo");
    [super foo];
}

@end

int main(void)
{
[[MacRuby sharedRuntime] evaluateString:@"class Foo; def foo; p :ruby_foo; end; end"];
    Class k = NSClassFromString(@"ObjCFoo");
    class_setSuperclass(k, NSClassFromString(@"Foo"));

    ObjCFoo *o = [[ObjCFoo alloc] init];
    [o foo];

    return 0;
}

$ gcc hello2.m -o hello2 -framework Foundation -framework MacRuby - fobjc-gc -arch i386 -arch x86_64
hello2.m: In function ‘main’:
hello2.m:25: warning: ‘class_setSuperclass’ is deprecated (declared at /usr/include/objc/runtime.h:126) hello2.m:25: warning: ‘class_setSuperclass’ is unavailable (declared at /usr/include/objc/runtime.h:126)
hello2.m: In function ‘main’:
hello2.m:25: warning: ‘class_setSuperclass’ is deprecated (declared at /usr/include/objc/runtime.h:126)

$ ./hello22009-04-17 22:53:55.596 hello2[67436:10b] objc_foo
:ruby_foo

3. If I were to call arbitrary scripts as in the embedding sample, how can I pre-initialize ruby objects so that they are available in the environment? I.e, if I allow the user to extend my app by running their ruby code, how can I make my objects available to him? And also, how could I prevent certain objects from being available to him, so that he doesn't break anything?

Once you link against MacRuby and call the -[sharedRuntime] method, all Ruby classes should be available in Objective-C. Ruby objects created from Objective-C must be referenced by Objective-C otherwise the garbage collector will free them. It is up to the developer to manage the Ruby objects created from Objective-C.

Vice-versa, Objective-C classes & objects are available in Ruby. There is no way to hide classes/objects, everything is dynamic.

HTH,
Laurent
_______________________________________________
MacRuby-devel mailing list
MacRuby-devel@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel

Reply via email to