Laurent Sansonetti
lsans****@apple*****
Thu Sep 28 01:59:08 JST 2006
Hi all, Some news regarding the recent work in the 'apple-unstable' branch! - Informal protocols are now handled in the XML files. At build time we describe them (via the gen_bridge_metadata script) and at runtime we build a hash table that maps selector to the method type (encoding) equivalent. DummyProtocolHandler has been removed. - The XML files can contain 'exceptions'. Exceptions are written in a separate XML file and the gen_bridge_metadata script will merge them to the final XML file. These exceptions describe pointer-like arguments, and also methods that should be ignored by the bridge (that we can't handle properly). The exceptions files are not yet committed to the SVN repository. Some examples here [1]. - libffi closures are now used in OverrideMixin as IMP method handlers, and in the closure code we directly call the embedded Ruby object. This is great because 1) we don't use NSInvocation anymore and 2) it now works with floating point arguments (this fixes bug #1535223 in SF.net). So faster and more reliable. - A bug was found in the memory retention code. Some classes (NSDictionary for example) always return the same object in [- alloc], and they return the real new ObjC object in the [-init] method. Ruby was keeping a Ruby'fied version of the singleton ObjC object and releasing it after garbage collection, which was crashing the next call to [NSDictionary alloc]. RubyCocoa was fixed to not mark objects from [-alloc] and [-allocWithZone:] to be released upon garbage collection. It appears that this problem is only on recent Mac OS X builds (10.5), so I didn't port the fix to the stable branch (yet). Laurent [1]: Calling an ignored method: irb(main):001:0> x = OSX::NSData.alloc.init => #<OSX::NSConcreteData:0x2307a class='NSConcreteData' id=0x3de8c0> irb(main):002:0> OSX::NSData.dataWithBytesNoCopy_length(nil) RuntimeError: Method 'dataWithBytesNoCopy:length:' is not supported (suggested alternative: 'Call dataWithBytes:length:.') from /Volumes/Data/src/svn-rubycocoa-apple/framework/build/ Default/RubyCocoa.framework/Versions/A/Resources/ruby/osx/objc/ oc_wrapper.rb:17:in `ocm_send' from /Volumes/Data/src/svn-rubycocoa-apple/framework/build/ Default/RubyCocoa.framework/Versions/A/Resources/ruby/osx/objc/ oc_wrapper.rb:17:in `method_missing' from (irb):2 Calling a method with an 'in' C-like array delimited by another argument. Note the warning that is raised by the first instruction, the 'length' argument is no longer needed, as we can determine it from the 'bytes' argument, thanks to the metadata. We also get the data after that (using the same way as before, but with an 'out' argument). irb(main):003:0> x = OSX::NSData.alloc.initWithBytes_length('foobar', 6) /Volumes/Data/src/svn-rubycocoa-apple/framework/build/Default/ RubyCocoa.framework/Versions/A/Resources/ruby/osx/objc/oc_wrapper.rb: 17: warning: NSConcreteData#initWithBytes:length: argument #1 is no longer necessary (will be ignored) => #<OSX::NSConcreteData:0x2fafa class='NSConcreteData' id=0x329b40> irb(main):004:0> x = OSX::NSData.alloc.initWithBytes_length('foobar') => #<OSX::NSConcreteData:0x1cc52 class='NSConcreteData' id=0x3e7510> irb(main):005:0> data = ' ' * 6 => " " irb(main):006:0> x.getBytes_length(data) => nil irb(main):007:0> p data "foobar" Calling a method with a C-like array of 'id' variables. We can determine from the ObjC runtime if a parameter is a pointer of 'id'. From the metadata we can know determine if it's a C-array, so instead of passing some kind of raw data, we can support a better way, as a real Ruby array of objects. irb(main):010:0> ary = OSX::NSArray.arrayWithObjects_count(['a', OSX::NSObject.alloc.init, OSX::NSNumber.numberWithFloat(3.141592)]) => #<OSX::NSCFArray:0x22454 class='NSCFArray' id=0x3702b0> irb(main):011:0> ary.objectAtIndex(0) => #<OSX::NSCFString:0x1fa10 class='NSCFString' id=0x3701e0> irb(main):012:0> ary.objectAtIndex(0).to_s => "a" irb(main):013:0> ary.objectAtIndex(1) => #<OSX::NSObject:0x23714 class='NSObject' id=0x378720> irb(main):014:0> ary.objectAtIndex(2) => #<OSX::NSCFNumber:0x22a12 class='NSCFNumber' id=0x3eb130> irb(main):015:0> ary.objectAtIndex(2).floatValue => 3.14159202575684 Finally, we also support methods with several C-like array but determined by the same 'length' argument. Passing 2 arrays of different length will raise an exception though. irb(main):020:0> keys = ['k1', 'k2'] => ["k1", "k2"] irb(main):021:0> dict = OSX::NSDictionary.dictionaryWithObjects_forKeys_count(['o1','o2'], keys) => #<OSX::NSCFDictionary:0x231c4 class='NSCFDictionary' id=0x3d2570> irb(main):022:0> dict.count => 2 irb(main):023:0> dict.objectForKey(keys.first).to_s => "o1" irb(main):024:0> dict.objectForKey(keys.last).to_s => "o2"