MRI-Binding: Bind #initialize_copy for clonable classes

This replaces the previously directly bound #clone
methods, which weren't really the "the Ruby way".
Rubys default Object#clone will call into our #init_copy
methods instead.

Partly incorporates pull request #3 by /cremno.
This commit is contained in:
Jonas Kulla 2013-10-31 10:13:24 +01:00
parent 7549778dc6
commit b7a2ba830c
4 changed files with 37 additions and 28 deletions

View File

@ -196,26 +196,16 @@ rb_bool_new(bool value)
return objectLoad<Typ>(argc, argv, self); \ return objectLoad<Typ>(argc, argv, self); \
} }
#define CLONE_FUNC(Klass) \ #define INITCOPY_FUN(Klass) \
static mrb_value \ RB_METHOD(Klass##InitializeCopy) \
Klass##Clone(mrb_state *mrb, mrb_value self) \
{ \ { \
Klass *k = getPrivateData<Klass>(mrb, self); \ VALUE orig; \
mrb_value dupObj = mrb_obj_clone(mrb, self); \ rb_get_args(argc, argv, "o", &orig, RB_ARG_END); \
Klass *dupK = new Klass(*k); \ if (!OBJ_INIT_COPY(self, orig)) /* When would this fail??*/\
setPrivateData(mrb, dupObj, dupK, Klass##Type); \ return self; \
return dupObj; \ Klass *k = getPrivateData<Klass>(orig); \
} setPrivateData(self, new Klass(*k)); \
return self; \
#define CLONE_FUN(Klass) \
RB_METHOD(Klass##Clone) \
{ \
RB_UNUSED_PARAM \
Klass *k = getPrivateData<Klass>(self); \
VALUE dupObj = rb_obj_clone(self); \
Klass *dupK = new Klass(*k); \
setPrivateData(dupObj, dupK); \
return dupObj; \
} }
/* If we're not binding a disposable class, /* If we're not binding a disposable class,

View File

@ -291,7 +291,7 @@ RB_METHOD(bitmapTextSize)
DEF_PROP_OBJ(Bitmap, Font, Font, "font") DEF_PROP_OBJ(Bitmap, Font, Font, "font")
CLONE_FUN(Bitmap) INITCOPY_FUN(Bitmap)
void void
@ -305,6 +305,7 @@ bitmapBindingInit()
disposableBindingInit<Bitmap>(klass); disposableBindingInit<Bitmap>(klass);
_rb_define_method(klass, "initialize", bitmapInitialize); _rb_define_method(klass, "initialize", bitmapInitialize);
_rb_define_method(klass, "initialize_copy", BitmapInitializeCopy);
_rb_define_method(klass, "width", bitmapWidth); _rb_define_method(klass, "width", bitmapWidth);
_rb_define_method(klass, "height", bitmapHeight); _rb_define_method(klass, "height", bitmapHeight);
@ -320,6 +321,4 @@ bitmapBindingInit()
_rb_define_method(klass, "text_size", bitmapTextSize); _rb_define_method(klass, "text_size", bitmapTextSize);
INIT_PROP_BIND(Bitmap, Font, "font"); INIT_PROP_BIND(Bitmap, Font, "font");
_rb_define_method(klass, "clone", BitmapClone);
} }

View File

@ -148,9 +148,9 @@ MARSH_LOAD_FUN(Color)
MARSH_LOAD_FUN(Tone) MARSH_LOAD_FUN(Tone)
MARSH_LOAD_FUN(Rect) MARSH_LOAD_FUN(Rect)
CLONE_FUN(Tone) INITCOPY_FUN(Tone)
CLONE_FUN(Color) INITCOPY_FUN(Color)
CLONE_FUN(Rect) INITCOPY_FUN(Rect)
#define INIT_BIND(Klass) \ #define INIT_BIND(Klass) \
{ \ { \
@ -160,8 +160,8 @@ CLONE_FUN(Rect)
rb_define_class_method(klass, "_load", Klass##Load); \ rb_define_class_method(klass, "_load", Klass##Load); \
serializableBindingInit<Klass>(klass); \ serializableBindingInit<Klass>(klass); \
_rb_define_method(klass, "initialize", Klass##Initialize); \ _rb_define_method(klass, "initialize", Klass##Initialize); \
_rb_define_method(klass, "initialize_copy", Klass##InitializeCopy); \
_rb_define_method(klass, "set", Klass##Set); \ _rb_define_method(klass, "set", Klass##Set); \
_rb_define_method(klass, "clone", Klass##Clone); \
_rb_define_method(klass, "==", Klass##Equal); \ _rb_define_method(klass, "==", Klass##Equal); \
_rb_define_method(klass, "to_s", Klass##Stringify); \ _rb_define_method(klass, "to_s", Klass##Stringify); \
_rb_define_method(klass, "inspect", Klass##Stringify); \ _rb_define_method(klass, "inspect", Klass##Stringify); \

View File

@ -54,6 +54,25 @@ RB_METHOD(fontInitialize)
return self; return self;
} }
RB_METHOD(fontInitializeCopy)
{
VALUE orig;
rb_get_args(argc, argv, "o", &orig, RB_ARG_END);
if (!OBJ_INIT_COPY(self, orig))
return self;
Font *f = getPrivateData<Font>(orig);
Font *dup = new Font(*f);
setPrivateData(self, dup);
/* Wrap property objects */
f->setColor(new Color(*f->getColor()));
wrapProperty(self, f->getColor(), "color", ColorType);
return self;
}
RB_METHOD(FontGetName) RB_METHOD(FontGetName)
{ {
RB_UNUSED_PARAM; RB_UNUSED_PARAM;
@ -165,6 +184,7 @@ fontBindingInit()
rb_define_class_method(klass, "exist?", fontDoesExist); rb_define_class_method(klass, "exist?", fontDoesExist);
_rb_define_method(klass, "initialize", fontInitialize); _rb_define_method(klass, "initialize", fontInitialize);
_rb_define_method(klass, "initialize_copy", fontInitializeCopy);
INIT_PROP_BIND(Font, Name, "name"); INIT_PROP_BIND(Font, Name, "name");
INIT_PROP_BIND(Font, Size, "size"); INIT_PROP_BIND(Font, Size, "size");