Revision: 1497 http://trac.macosforge.org/projects/ruby/changeset/1497 Author: lsansonetti@apple.com Date: 2009-04-27 21:25:21 -0700 (Mon, 27 Apr 2009) Log Message: ----------- more Pointer work (should be almost done) + misc fixes Modified Paths: -------------- MacRuby/branches/experimental/roxor.cpp MacRuby/branches/experimental/spec/macruby/pointer_spec.rb Modified: MacRuby/branches/experimental/roxor.cpp =================================================================== --- MacRuby/branches/experimental/roxor.cpp 2009-04-28 03:11:40 UTC (rev 1496) +++ MacRuby/branches/experimental/roxor.cpp 2009-04-28 04:25:21 UTC (rev 1497) @@ -5624,6 +5624,7 @@ return Type::Int32Ty; case _C_LNG: + case _C_ULNG: #if __LP64__ return Type::Int64Ty; #else @@ -5659,8 +5660,7 @@ break; } - printf("unrecognized runtime type `%s' - aborting\n", type); - abort(); + rb_raise(rb_eTypeError, "unrecognized runtime type `%s'\n", type); } Function * @@ -9085,15 +9085,22 @@ void *val; } rb_vm_pointer_t; +static const char *convert_ffi_type(VALUE type, + bool raise_exception_if_unknown); + static VALUE -rb_pointer_new(VALUE rcv, SEL sel, VALUE type) +rb_pointer_new(VALUE rcv, SEL sel, int argc, VALUE *argv) { + VALUE type, len; + rb_scan_args(argc, argv, "11", &type, &len); + const size_t rlen = NIL_P(len) ? 1 : FIX2LONG(len); + StringValuePtr(type); + const char *type_str = convert_ffi_type(type, false); rb_vm_pointer_t *ptr = (rb_vm_pointer_t *)xmalloc(sizeof(rb_vm_pointer_t)); - GC_WB(&ptr->type, type); + GC_WB(&ptr->type, rb_str_new2(type_str)); - const char *type_str = RSTRING_PTR(type); ptr->convert_to_rval = (VALUE (*)(void *))GET_VM()->gen_to_rval_convertor(type_str); ptr->convert_to_ocval = @@ -9101,7 +9108,7 @@ ptr->type_size = GET_VM()->get_sizeof(type_str); assert(ptr->type_size > 0); - GC_WB(&ptr->val, xmalloc(ptr->type_size)); + GC_WB(&ptr->val, xmalloc(ptr->type_size * rlen)); return Data_Wrap_Struct(rb_cPointer, NULL, NULL, ptr); } @@ -9152,6 +9159,7 @@ void Init_BridgeSupport(void) { + // Boxed rb_cBoxed = rb_define_class("Boxed", rb_cObject); rb_objc_define_method(*(VALUE *)rb_cBoxed, "type", (void *)rb_boxed_objc_type, 0); @@ -9159,11 +9167,12 @@ (void *)rb_boxed_is_opaque, 0); boxed_ivar_type = rb_intern("__octype__"); + // Pointer rb_cPointer = rb_define_class("Pointer", rb_cObject); rb_objc_define_method(*(VALUE *)rb_cPointer, "new", - (void *)rb_pointer_new, 1); + (void *)rb_pointer_new, -1); rb_objc_define_method(*(VALUE *)rb_cPointer, "new_with_type", - (void *)rb_pointer_new, 1); + (void *)rb_pointer_new, -1); rb_objc_define_method(rb_cPointer, "[]", (void *)rb_pointer_aref, 1); rb_objc_define_method(rb_cPointer, "[]=", @@ -9515,12 +9524,12 @@ // FFI static const char * -convert_ffi_type(VALUE type) +convert_ffi_type(VALUE type, bool raise_exception_if_unknown) { const char *typestr = StringValueCStr(type); assert(typestr != NULL); - // Converting Ruby-FFI types to Objective-C runtime types. + // Ruby-FFI types. if (strcmp(typestr, "char") == 0) { return "c"; @@ -9565,8 +9574,17 @@ return "^"; } - rb_raise(rb_eArgError, "unrecognized string `%s' given as FFI type", - typestr); + // MacRuby extensions. + + if (strcmp(typestr, "object") == 0) { + return "@"; + } + + if (raise_exception_if_unknown) { + rb_raise(rb_eTypeError, "unrecognized string `%s' given as FFI type", + typestr); + } + return typestr; } Function * @@ -9644,12 +9662,12 @@ } std::string types; - types.append(convert_ffi_type(ret)); + types.append(convert_ffi_type(ret, true)); Check_Type(args, T_ARRAY); const int argc = RARRAY_LEN(args); for (int i = 0; i < argc; i++) { - types.append(convert_ffi_type(RARRAY_AT(args, i))); + types.append(convert_ffi_type(RARRAY_AT(args, i), true)); } rb_vm_c_stub_t *stub = (rb_vm_c_stub_t *)GET_VM()->gen_stub(types, argc, Modified: MacRuby/branches/experimental/spec/macruby/pointer_spec.rb =================================================================== --- MacRuby/branches/experimental/spec/macruby/pointer_spec.rb 2009-04-28 03:11:40 UTC (rev 1496) +++ MacRuby/branches/experimental/spec/macruby/pointer_spec.rb 2009-04-28 04:25:21 UTC (rev 1497) @@ -3,7 +3,6 @@ framework 'Foundation' describe "A Pointer object" do -=begin # TODO it "can be created using the #new class method and with a valid Objective-C type or a valid Symbol object" do types = { :object => '@', @@ -31,22 +30,70 @@ end lambda { Pointer.new }.should raise_error(ArgumentError) - lambda { Pointer.new('invalid') }.should raise_error(TypeError) + lambda { Pointer.new(nil) }.should raise_error(TypeError) + lambda { Pointer.new(123) }.should raise_error(TypeError) + lambda { Pointer.new('x') }.should raise_error(TypeError) + + p = Pointer.new(NSRect.type) + p.type.should == NSRect.type end -=end -=begin # TODO - it "can be assigned an object of the given type and retrieve it later, using #[] and #[]=" - p = Pointer.new('@') + it "can be assigned an object of the given type and retrieve it later, using #[] and #[]=" do + p = Pointer.new('object') o = Object.new p[0] = o + p[0].object_id.should == o.object_id p[0].should == o - p = Pointer.new('i') - p[0] = 42 - p[0].should == 42 + p[0] = 123 + p[0].class.should == Fixnum + p[0].should == 123 - lambda { p[0] = Object.new }.should raise_error(TypeError) + int_types = %w{ char uchar short ushort int uint long ulong + long_long ulong_long } + int_types.each do |t| + p = Pointer.new(t) + p[0] = 42 + p[0].class.should == Fixnum + p[0].should == 42 + + o = Object.new + def o.to_i; 42; end + + p[0] = o + p[0].class.should == Fixnum + p[0].should == 42 + + lambda { p[0] = Object.new }.should raise_error(TypeError) + end + + float_types = %w{ float double } + float_types.each do |t| + p = Pointer.new(t) + p[0] = 42 + p[0].class.should == Float + p[0].should == 42.0 + + o = Object.new + def o.to_f; 42.0; end + + p[0] = o + p[0].class.should == Float + p[0].should == 42.0 + + lambda { p[0] = Object.new }.should raise_error(TypeError) + end + + struct_types = [[NSPoint, NSPoint.new(1, 2)], + [NSSize, NSSize.new(3, 4)], + [NSRect, NSRect.new(NSPoint.new(1, 2), NSSize.new(3, 4))]] + struct_types.each do |k, o| + p = Pointer.new(k.type) + p[0] = o + p[0].class.should == k + p[0].should == o + + lambda { p[0] = Object.new }.should raise_error(TypeError) + end end -=end end