なかだです。

At Thu, 11 Dec 2003 15:29:10 +0900,
katata / chugoku-pc.ac.jp wrote:
> > > | require 'DirectXGraphicsTest'
> > > | 
> > > | test1 = D3D::MATERIAL9.new( )
> > >   d = test1.Diffuse
> > >   d.r = 1.0
> > > | 
> > > | while true
> > >     puts d.r
> > > | end
> > > 
> > > とすると大丈夫だったりしませんかね。
> 
> それは大丈夫でした。
> たまたまなのかもしれませんが、私の方ではエラーにならなかったです。

test1もdも最後まで使われているからです。test1がGCされた時点でd
の指す領域も無効になりますし、dがGCされるとおそらくヒープが破壊
されます。

> > 解放されるときにmalloc()されたのでないポインタをfree()しようと
> > しています。COLORVALUE自身はfreeしないようにして、dmarkで
> > MATERIAL9をマークするようにすればうまくいくかも知れません。
> 
> Drap_Wrap_Structにでてくるmarkの意味と具体的な利用方法が全く理解できてい
> ない私ですが、なかださんの添付ファイルを利用してみたところ、ばっちりうま
> くいきました。

mD3D_cD3DCOLORVALUE_mark()に渡されたポインタは別の構造体の一部
なので、その構造体全体が解放されないように、それをラップしてい
るオブジェクトをマークする必要があります。このポインタから別オ
ブジェクトへの対応を、ハッシュで管理しています。

GCされたときは、構造体の一部を指すポインタを解放してはいけない
ので、直接解放する代わりにmD3D_cD3DCOLORVALUE_unref()でその対応
付けを消しています。

ハッシュで管理する以外にも、間接参照用のデータを使う方法も考え
られます。

    typedef struct {
	void *data;
	VALUE obj;
    } partial_ptr_t;

    static void
    mark_original(void *ptr)
    {
    }

    static void
    free_original(void *ptr)
    {
	free(((partial_ptr_t *)ptr)->data);
	free(ptr);
    }

    static void
    mark_partial(void *ptr)
    {
	rb_gc_mark(((partial_ptr_t *)ptr)->obj);
    }

    static void
    free_partial(void *ptr)
    {
	free(ptr);
    }

mark&freeは簡単になるかも知れませんが、すべてのメソッドでポイン
タを余分にたどることになります。

> ところでこのプログラムはRuby-1.8用ですよね?
> 1.6.8ではst_data_tが定義されてませんでした。

うっかりしてました。#include <st.h>の後にでも入れてください。

  #ifndef ST_DATA_T_DEFINED
  typedef void *st_data_t;
  #endif 

それと、HAVE_RB_DEFINE_ALLOC_FUNCはintern.hで定義済みなので、
extconf.rbの have_func("rb_define_alloc_func", "ruby.h") は不要
でした。

> それからst.hのドキュメントってどこかにあるのでしょうか?

あったかなぁ。st.c?
ないような気がするのでちょっと書いてみました。
http://nokada.jin.gr.jp/ruby/st.rd

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