なかだです。

なかだです。

At Thu, 08 Jul 2004 18:30:43 +0900,
米倉正和 wrote in [ruby-ext:02284]:
> // wrap => IplImageをRubyのオブジェクトでwrapする場合に使う
> VALUE Object_IplImage::wrap(IplImage *ptr){
>   VALUE object = alloc(RubyClass);
>   (IplImage*)DATA_PTR(object) = ptr;
>   return object;
> }

ここで、IplImage*と元になるVALUEを持つ構造体を間に入れるという
ことです。

    class Object_IplImage
    {
      private:
        IplImage* image;
        VALUE origin;
      public:
        Object_IplImage(IplImage *ptr, VALUE orig = 0)
            : image(ptr), origin(orig) {}
        VALUE wrap();
    };

    VALUE Object_IplImage::wrap() {
        VALUE object = alloc(RubyClass);
        DATA_PTR(object) = (void *)this;
        return object;
    }

これだとほとんどのメソッドで間接参照が一回増えることになるので、
それがいやならばIplImage*から元のVALUEへのハッシュを使うという
方法もあります。


    class Object_IplImage
    {
      private:
        static st_table *origin;
        static void mark(void *);
        static void free(void *);
    };

    st_table *Object_IplImage::origin = st_init_numtable();

    VALUE Object_IplImage::alloc(VALUE self)
    {
        return Data_Make_Struct(self, IplImage, mark, free, 0);
    }

    void Object_IplImage::mark(void *ptr)
    {
        st_data_t val;
        if (st_lookup(origin, (st_data_t)ptr, &val))
            rb_gc_mark((VALUE)val);
    }

    void Object_IplImage::free(void *ptr)
    {
        st_data_t img = (st_data_t)ptr;
        st_delete(origin, img, 0);
        xfree(ptr);
    }


もう一つ、ちょっと気になったのですが、これではalloc()で確保され
たIplImageはinitialize()で上書きされてしまい、メモリリークしま
せんか。

> // alloc => 領域を確保
> VALUE Object_IplImage::alloc(VALUE self){
>   IplImage *ptr;
>   return Data_Make_Struct(self, IplImage, 0, free, ptr);
> }
> 
> // initialize
> VALUE Object_IplImage::initialize(VALUE self, VALUE width, VALUE height){
>   // --- IplImage *imageを作成(省略) ---
>   DATA_PTR(self) = image;
>   return self;
> }

-- 
--- 僕の前にBugはない。
--- 僕の後ろにBugはできる。
    中田 伸悦