[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