[macruby-changes] [367] MacRuby/trunk

source_changes at macosforge.org source_changes at macosforge.org
Thu Jul 10 18:27:03 PDT 2008


Revision: 367
          http://trac.macosforge.org/projects/ruby/changeset/367
Author:   lsansonetti at apple.com
Date:     2008-07-10 18:27:02 -0700 (Thu, 10 Jul 2008)
Log Message:
-----------
introducing Pointer class to wrap C pointers, fixed a bug in the ruby->objc dispatcher

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

Modified: MacRuby/trunk/objc.m
===================================================================
--- MacRuby/trunk/objc.m	2008-07-11 00:40:01 UTC (rev 366)
+++ MacRuby/trunk/objc.m	2008-07-11 01:27:02 UTC (rev 367)
@@ -621,8 +621,44 @@
     return n;
 }
 
+VALUE rb_cPointer;
+
+struct RPointer
+{
+  void *ptr;
+  const char *type;
+};
+
+static VALUE
+rb_pointer_create(void *ptr, const char *type)
+{
+    struct RPointer *data;
+
+    data = (struct RPointer *)xmalloc(sizeof(struct RPointer ));
+    data->ptr = ptr;
+    data->type = type;
+
+    return Data_Wrap_Struct(rb_cPointer, NULL, NULL, data);
+}
+
 static void rb_objc_rval_to_ocval(VALUE, const char *, void **);
 
+static VALUE
+rb_pointer_assign(VALUE recv, VALUE val)
+{
+    struct RPointer *data;
+
+    Data_Get_Struct(recv, struct RPointer, data);
+
+    assert(data != NULL);
+    assert(data->ptr != NULL);
+    assert(data->type != NULL);
+
+    rb_objc_rval_to_ocval(val, data->type, data->ptr);
+
+    return val;
+}
+
 static void *
 rb_objc_rval_to_boxed_data(VALUE rval, bs_element_boxed_t *bs_boxed, bool *ok)
 {
@@ -988,8 +1024,7 @@
 		*rbval = Qnil;
 	    }
 	    else {
-		/* TODO: wrap C pointers into a specific object */
-		ok = false;
+		*rbval = rb_pointer_create(*(void **)ocval, octype + 1);
 	    }
 	    break;
 
@@ -1153,10 +1188,8 @@
 	    imp = ctx->imp;
 	}
 	else {
-	    ctx->imp = imp = ctx->method == 
-		class_getInstanceMethod(klass, ctx->selector)
-		    ? method_getImplementation(ctx->method)
-		    : objc_msgSend; /* alea jacta est */
+	    ctx->imp = imp = method_getImplementation(ctx->method);
+	    ctx->klass = klass;
 	}
     }
 
@@ -1260,7 +1293,7 @@
 	assert(ctx->method != NULL);
 	ctx->cif = NULL;
 	ctx->imp = NULL;
-	ctx->klass = NULL;
+	ctx->klass = klass;
 	GC_WB(&rb_current_cfunc_node->u3.value, ctx);
     }
     else {
@@ -3077,6 +3110,10 @@
     rb_define_singleton_method(rb_cBoxed, "opaque?", rb_boxed_is_opaque, 0);
     rb_define_singleton_method(rb_cBoxed, "fields", rb_boxed_fields, 0);
 
+    rb_cPointer = rb_define_class("Pointer", rb_cObject);
+    rb_undef_alloc_func(rb_cPointer);
+    rb_define_method(rb_cPointer, "assign", rb_pointer_assign, 1);
+
     rb_ivar_type = rb_intern("@__objc_type__");
 
     rb_install_objc_primitives();

Modified: MacRuby/trunk/test/ruby/test_objc.rb
===================================================================
--- MacRuby/trunk/test/ruby/test_objc.rb	2008-07-11 00:40:01 UTC (rev 366)
+++ MacRuby/trunk/test/ruby/test_objc.rb	2008-07-11 01:27:02 UTC (rev 367)
@@ -1,5 +1,66 @@
 require 'test/unit'
 
+DUMMY_M = <<END_DUMMY_M
+#import <Foundation/Foundation.h>
+
+ at interface TestGetMethod : NSObject
+ at end
+
+ at implementation TestGetMethod
+- (void)getInt:(int *)v {}
+- (void)getLong:(long *)l {}
+- (void)getObject:(id *)o {}
+- (void)getRect:(NSRect *)r {}
+ at end
+
+ at interface Dummy : NSObject
+ at end
+
+ at implementation Dummy
+
+- (void)testCallGetIntMethod:(id)receiver expectedValue:(int)val
+{
+    int i = 0;
+    [(TestGetMethod *)receiver getInt:&i];
+    if (i != val)
+        [NSException raise:@"testCallGetIntMethod" format:@"expected %d, got %d", val, i];
+}
+
+- (void)testCallGetLongMethod:(id)receiver expectedValue:(long)val
+{
+    long l = 0;
+    [(TestGetMethod *)receiver getLong:&l];
+    if (l != val)
+        [NSException raise:@"testCallGetLongMethod" format:@"expected %ld, got %ld", val, l];
+}
+
+- (void)testCallGetObjectMethod:(id)receiver expectedValue:(id)val
+{
+    id o = nil;
+    [(TestGetMethod *)receiver getObject:&o];
+    if (o != val)
+        [NSException raise:@"testCallGetLongMethod" format:@"expected %p, got %p", val, o];
+}
+
+- (void)testCallGetRectMethod:(id)receiver expectedValue:(NSRect)val
+{
+    NSRect r = NSZeroRect;
+    [(TestGetMethod *)receiver getRect:&r];
+    if (!NSEqualRects(r, val)) 
+        [NSException raise:@"testCallGetLongMethod" format:@"expected %@, got %@", NSStringFromRect(val), NSStringFromRect(r)];
+}
+
+ at end
+
+void Init_dummy(void) {}
+END_DUMMY_M
+
+if !File.exist?('/tmp/dummy.bundle') or File.mtime(__FILE__) > File.mtime('/tmp/dummy.bundle')
+  File.open('/tmp/dummy.m', 'w') { |io| io.write(DUMMY_M) }
+  system("/usr/bin/gcc /tmp/dummy.m -o /tmp/dummy.bundle -g -framework Foundation -dynamiclib -fobjc-gc")
+end
+require '/tmp/dummy.bundle'
+
 class TestObjC < Test::Unit::TestCase
 
   def setup
@@ -226,5 +287,27 @@
     assert_equal('xxx', o.bar)
   end
 
+  class RubyTestGetMethod < TestGetMethod
+    attr_accessor :tc, :val
+    [:getInt, :getLong, :getObject, :getRect].each do |s|
+      define_method(s) do |ptr|
+        @tc.assert_kind_of(Pointer, ptr)
+        ptr.assign(@val)
+      end
+    end
+  end
+  def test_call_get_int
+    d = Dummy.new
+    obj = RubyTestGetMethod.new
+    obj.tc = self
+    obj.val = 42
+    d.testCallGetIntMethod(obj, expectedValue:obj.val)
+    obj.val = 42_000_000
+    d.testCallGetLongMethod(obj, expectedValue:obj.val)
+    obj.val = d
+    d.testCallGetObjectMethod(obj, expectedValue:obj.val)
+    obj.val = NSRect.new(NSPoint.new(1, 2), NSSize.new(3, 4))
+    d.testCallGetRectMethod(obj, expectedValue:obj.val)
+  end
+
 end
-
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/macruby-changes/attachments/20080710/b0feee54/attachment.html 


More information about the macruby-changes mailing list