从我的Ruby C扩展我想从Google SketchUp Ruby API创建一个新的Geom::Vector3d
实例:https://developers.google.com/sketchup/docs/ourdoc/vector3d
我的初始代码是:
static inline VALUE
vector_to_sketchup( Point3d vector )
{
VALUE skp_vector, args[3];
args[0] = rb_float_new( vector.x );
args[1] = rb_float_new( vector.y );
args[2] = rb_float_new( vector.z );
skp_vector = rb_class_new_instance( 3, args, cVector3d );
}
然而这引起了一个错误:
Error: #<ArgumentError: wrong type - expected Sketchup::Vector3d>
相反,我不得不调用ruby new
方法 - 就像这样:
static inline VALUE
vector_to_sketchup( Point3d vector )
{
VALUE skp_vector;
skp_vector = rb_funcall( cVector3d, sNew, 3,
rb_float_new( vector.x ),
rb_float_new( vector.y ),
rb_float_new( vector.z )
);
return skp_vector;
}
我遇到了与Geom::Point3d和Sketchup::Color相同的问题。
rb_class_new_instance
是在Ruby C中创建新实例的首选方法,对吧?
任何人都知道为什么我需要拨打new
?关于如何在SketchUp中定义类的一些奇怪之处?
答案 0 :(得分:0)
在与Google SketchUp的开发者沟通后,我找到了原因。
SketchUp使用Data_Wrap_Struct
将他们的C类与Ruby类链接起来。但是他们使用一种分配数据的旧方法 - 这是在#new
方法中。
在Ruby 1.8中,您使用rb_define_alloc_func()
进行分配,而您永远不会使用#new
。 Ruby(1.6和1.8)定义#new
来调用rb_class_new_instance()
。
由于我在SketchUp的旧样式类中使用了rb_class_new_instance()
未正确创建的对象,因此绕过了分配函数并且从未触发过。我得到的错误来自SketchUp,而不是Ruby。
答案是,您可以使用rb_class_new_instance()
创建新的类实例,前提是它们没有重载#new
方法来进行任何初始化。在Ruby 1.6之前,如果需要分配数据,这对于Ruby C类来说很常见,但是从1.8开始, 应该用rb_define_alloc_func()
来完成。 (马茨在这里说:http://www.justskins.com/forums/the-new-allocation-scheme-132572.html#post437362)
您可以在这篇文章中看到Ruby 1.6样式和1.8样式之间的差异:http://www.justskins.com/forums/the-new-allocation-scheme-132572.html#post444948