[macruby-changes] [118] MacRuby/trunk

source_changes at macosforge.org source_changes at macosforge.org
Sun Mar 23 19:19:41 PDT 2008


Revision: 118
          http://trac.macosforge.org/projects/ruby/changeset/118
Author:   lsansonetti at apple.com
Date:     2008-03-23 19:19:40 -0700 (Sun, 23 Mar 2008)

Log Message:
-----------
boxed types are now valid NSValue subclasses

Modified Paths:
--------------
    MacRuby/trunk/objc.m
    MacRuby/trunk/test-macruby/test_boxed.rb
    MacRuby/trunk/test-macruby/test_objc.rb

Modified: MacRuby/trunk/objc.m
===================================================================
--- MacRuby/trunk/objc.m	2008-03-23 04:02:19 UTC (rev 117)
+++ MacRuby/trunk/objc.m	2008-03-24 02:19:40 UTC (rev 118)
@@ -2498,6 +2498,39 @@
     rb_funcall((VALUE)rcv, rb_intern("replace"), 1, newstr);
 }
 
+static const char *
+imp_rb_boxed_objCType(void *rcv, SEL sel)
+{
+    VALUE klass, type;
+
+    klass = CLASS_OF(rcv);
+    type = rb_boxed_objc_type(klass);
+    
+    return StringValuePtr(type);
+}
+
+static void
+imp_rb_boxed_getValue(void *rcv, SEL sel, void *buffer)
+{
+    bs_element_boxed_t *bs_boxed;
+    void *data;
+    bool ok;  
+
+    bs_boxed = rb_klass_get_bs_boxed(CLASS_OF(rcv));
+
+    data = bs_element_boxed_get_data(bs_boxed, (VALUE)rcv, &ok);
+    if (!ok)
+	[NSException raise:@"NSException" 
+	    format:@"can't get internal data for boxed type `%s'",
+	    RSTRING_PTR(rb_inspect((VALUE)rcv))];
+    if (data == NULL) {
+	*(void **)buffer = NULL; 
+    }
+    else {
+ 	memcpy(buffer, data, bs_boxed->ffi_type->size);
+    }
+}
+
 static inline void
 rb_objc_install_method(Class klass, SEL sel, IMP imp)
 {
@@ -2545,8 +2578,16 @@
 	(IMP)imp_rb_string_characterAtIndex);
     rb_objc_install_method(klass, @selector(getCharacters:range:),
 	(IMP)imp_rb_string_getCharactersRange);
-    rb_objc_install_method(klass, @selector(replaceCharactersInRange:withString:), 
+    rb_objc_install_method(klass, 
+	@selector(replaceCharactersInRange:withString:), 
 	(IMP)imp_rb_string_replaceCharactersInRangeWithString);
+
+    /* Boxed */
+    klass = RCLASS_OCID(rb_cBoxed);
+    rb_objc_override_method(klass, @selector(objCType), 
+	(IMP)imp_rb_boxed_objCType);
+    rb_objc_override_method(klass, @selector(getValue:), 
+	(IMP)imp_rb_boxed_getValue);
 }
 
 static void *
@@ -2780,7 +2821,8 @@
     rb_objc_retain(
 	rb_objc_class_magic_cookie = rb_str_new2("rb_objc_class_magic_cookie"));
 
-    rb_cBoxed = rb_define_class("Boxed", rb_cObject);
+    rb_cBoxed = rb_define_class("Boxed",
+	rb_objc_import_class(objc_getClass("NSValue")));
     rb_define_singleton_method(rb_cBoxed, "objc_type", rb_boxed_objc_type, 0);
     rb_define_singleton_method(rb_cBoxed, "opaque?", rb_boxed_is_opaque, 0);
     rb_define_singleton_method(rb_cBoxed, "fields", rb_boxed_fields, 0);

Modified: MacRuby/trunk/test-macruby/test_boxed.rb
===================================================================
--- MacRuby/trunk/test-macruby/test_boxed.rb	2008-03-23 04:02:19 UTC (rev 117)
+++ MacRuby/trunk/test-macruby/test_boxed.rb	2008-03-24 02:19:40 UTC (rev 118)
@@ -4,9 +4,78 @@
 
   def setup
     framework 'Foundation'
+    bundle = '/tmp/_test_bs.bundle'
+    if !File.exist?(bundle) or File.mtime(bundle) < File.mtime(__FILE__)
+      s = <<EOS
+#import <Foundation/Foundation.h>
+ at interface NSObject (MacRubyNSPointAdditions)
+- (float)x;
+- (float)y;
+ at end
+ at interface TestBoxed : NSObject
+ at end
+ at implementation TestBoxed
+- (void)testPoint:(NSPoint)point x:(float)x y:(float)y
+{
+    if (point.x != x)
+        [NSException raise:@"NSException"
+            format:@"point.x (%f) != x (%f)", point.x, x];
+  
+    if (point.y != y) 
+        [NSException raise:@"NSException"
+            format:@"point.y (%f) != y (%f)", point.y, y];
+}
+- (void)testPointAsObject:(id)point x:(float)x y:(float)y
+{
+    Class boxed;
+    boxed = NSClassFromString(@"Boxed");
+
+    if (![point isKindOfClass:boxed]) 
+        [NSException raise:@"NSException"
+            format:@"point (%@) isn't a boxed type", point];
+
+    if (![point isKindOfClass:[NSValue class]]) 
+        [NSException raise:@"NSException"
+            format:@"point (%@) isn't a value type", point];
+
+#if 0 // FIXME this cannot be tested yet 
+    if ([point x] != x)       
+        [NSException raise:@"NSException"
+            format:@"[point x] (%f) != x (%f)", [point x], x];
+
+    if ([point y] != y)       
+        [NSException raise:@"NSException"
+            format:@"[point y] (%f) != y (%f)", [point y], y];
+#endif
+
+    if (strcmp([point objCType], @encode(NSPoint)) != 0)
+        [NSException raise:@"NSException"
+            format:@"[point objCType] (%s) != @encode(NSPoint) (%s)", 
+	    [point objCType], @encode(NSPoint)];
+
+    NSPoint p;
+    [point getValue:&p];
+    [self testPoint:p x:x y:y];   
+}
+- (NSPoint)testReturnPointWithX:(float)x y:(float)y
+{
+    NSPoint p;
+    p.x = x;
+    p.y = y;
+    return p;
+}
+ at end
+EOS
+      File.open('/tmp/_test.m', 'w') { |io| io.write(s) }
+      system("gcc /tmp/_test.m -bundle -o #{bundle} -framework Foundation -fobjc-gc-only") or exit 1
+    end
+    require 'dl'; DL.dlopen(bundle)
   end
   
   def test_boxed_classes
+    assert_kind_of(Class, Boxed)
+    assert_equal(NSValue, Boxed.superclass)
+
     # struct
     assert(NSRect.ancestors.include?(Boxed))
     assert('{_NSRect={_NSPoint=ff}{_NSSize=ff}}', NSRect.objc_type)
@@ -80,14 +149,32 @@
   end
 
   def test_struct_nsstring_marshalling
-    r = NSRange.new(1.0, 4.0)
+    r = NSRange.new(1, 4)
     assert_kind_of(NSString, NSStringFromRange(r))
-    # FIXME not passing yet 
-    #assert_equal('{1.0, 4.0}', NSStringFromRange(r))
+    assert_equal('{1, 4}', NSStringFromRange(r))
     assert_equal(r, NSRangeFromString(NSStringFromRange(r)))
     rect = NSRect.new(NSPoint.new(42.0, 1042.0), NSSize.new(123, 456))
     assert_equal(NSPoint.new(42.0, 1042.0),
       NSPointFromString(NSStringFromPoint(rect.origin)))
   end
 
+  def test_nspoint_in_objc
+    p = NSPoint.new(42.0, 99.0)
+    o = TestBoxed.new
+    o.testPoint(p, x:42.0, y:99.0)
+    o.testPointAsObject(p, x:42.0, y:99.0)
+    assert_equal(p, o.testReturnPointWithX(42.0, y:99.0))
+  end
+
+  class MethodReturningBoxed
+    def foo
+      NSPoint.new(1, 2)
+    end
+  end
+  def test_objc_call_pure_method_returning_boxed
+    o = MethodReturningBoxed.new
+    assert_equal(NSPoint.new(1, 2), o.send(:foo))
+    assert_equal(NSPoint.new(1, 2), o.performSelector(:foo))
+  end
+
 end

Modified: MacRuby/trunk/test-macruby/test_objc.rb
===================================================================
--- MacRuby/trunk/test-macruby/test_objc.rb	2008-03-23 04:02:19 UTC (rev 117)
+++ MacRuby/trunk/test-macruby/test_objc.rb	2008-03-24 02:19:40 UTC (rev 118)
@@ -109,15 +109,4 @@
     assert_equal(v, o.test_getObject(dict, forKey:s))
   end
 
-  class MethodReturningBoxed
-    def foo
-      NSPoint.new(1, 2)
-    end
-  end
-  def test_objc_call_pure_method_returning_boxed
-    o = MethodReturningBoxed.new
-    assert_equal(NSPoint.new(1, 2), o.send(:foo))
-    assert_equal(NSPoint.new(1, 2), o.performSelector(:foo))
-  end
-
 end

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/macruby-changes/attachments/20080323/a6462d0e/attachment-0001.html 


More information about the macruby-changes mailing list