rb_class_new_instance引发“ArgumentError:错误类型” - 为什么?

时间:2012-03-12 13:56:29

标签: c ruby-c-extension

从我的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::Point3dSketchup::Color相同的问题。

rb_class_new_instance是在Ruby C中创建新实例的首选方法,对吧? 任何人都知道为什么我需要拨打new?关于如何在SketchUp中定义类的一些奇怪之处?

1 个答案:

答案 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