Hello Victor, I see that there is not much action on the list at the moment - so I will reply - the heavyweights do eventually drop by - but they are very busy so it is a bit sporadic (unless its just my gmail playing up again). I haven't actually tried 2 and 3 on your list since I am trying to obviate the need to actually write anything in Objective C. I guess if you have Obj C code already then you might want to call ruby rather than the other way around, so I will leave those questions for others and answer the simple one. For number 1: If you are using Xcode it all seems to work magically, and I am not sure why you are having problems. If I want to call some Obj C code from a ruby class - i first create an obj c class (eg MyClass) the normal way in Xcode (with .m and .h classes becoming part of the project), write the obj c code, and then any ruby code can magically use that class - eg with: MyClass.my_class_method or a = MyClass.new a.my_instance_method or a =MyClass.init.alloc a.my_instance_method if you want to access state in the obj c class - there was a thread on that recently (subject Accessing Obj-C InstVars from Ruby) - but I use getters and setters in the Obj C code. Hope that helps, John On Apr 16, 2009, at 13:23 , macruby-devel@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) 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) 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?
TIA,
victor _______________________________________________ MacRuby-devel mailing list MacRuby-devel@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
Hi Victor, On Apr 16, 2009, at 4:23 AM, macruby-devel@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
participants (3)
-
John Shea
-
Laurent Sansonetti
-
macruby-devel@principia.info