我正在爲物理引擎編寫Ruby擴展。這個物理引擎有機構鏈接到一個世界,所以我的Ruby對象是World
和Body
。一個身體構建(用C++)world->CreateBody
和銷燬與world->DestroyBody
。Data_Wrap_Struct和銷燬命令
問題是Ruby GC正在破壞身體之前的世界。所以,當GC摧毀身體時,世界不再存在,我得到了一個分割錯誤。我知道我需要在GC的某處標記某些東西(使用rb_gc_mark
),但我不知道在哪裏。
的World
類是非常標準的,它看起來像這樣:
extern "C" void world_free(void *w)
{
static_cast<World*>(w)->~World();
ruby_xfree(w);
}
extern "C" void world_mark(void *w)
{
// ???
}
extern "C" VALUE world_alloc(VALUE klass)
{
return Data_Wrap_Struct(klass, world_mark, world_free, ruby_xmalloc(sizeof(World)));
}
extern "C" VALUE world_initialize(VALUE self)
{
World* w;
Data_Get_Struct(self, World, w);
new (w) World();
return self;
}
的Body
類是有一點不同,因爲它需要從世界對象創建(我不能簡單地它)。所以它看起來像這樣:
extern "C" void body_free(void* b)
{
Body* body = static_cast<Body*>(b);
World* world = body->GetWorld();
world->DestroyBody(body);
}
extern "C" void body_mark(void* b)
{
// ???
}
extern "C" VALUE body_alloc(VALUE klass)
{
return Data_Wrap_Struct(klass, body_mark, body_free, 0);
}
extern "C" VALUE static_obj_initialize(VALUE self, VALUE world)
{
Body* b;
World* w;
Data_Get_Struct(self, Body, b);
Data_Get_Struct(world, World, w);
b = w->CreateBody();
DATA_PTR(self) = b;
return self;
}
所以我的問題是:
- 這兩個對象,我應該在GC標記的?
- 我該怎麼做?我是否只需標記
rb_gc_mark
,還是應該在某些情況下才做?哪個? - 我應該做什麼?標記函數僅接收到一個指向我的結構的裸指針,但函數
rb_gc_mark
需要VALUE
。
我不認爲'rb_gc_mark'會在這裏幫助 - 如果整個世界主體結構變得無法訪問,那麼就沒有辦法(據我所知)來控制自由函數被調用的順序。問題是釋放一個'Body'的函數取決於相應的'World'的存在。它看起來像庫的C++ API沒有乾淨地映射到一個Ruby API,其中'Worlds'和'Body's是獨立的對象 - 您可能需要重新考慮如何創建和處理對象以及它們的生命週期。 – matt
我明白了。問題在於對象在外部庫中 - 也就是說,我無法控制它。 –