0

从我的 Ruby C 扩展中,我想Geom::Vector3d从 Google SketchUp Ruby API 创建一个新实例: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>

相反,我不得不调用 rubynew​​ 方法——就像这样:

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 中类的定义方式有些奇怪?

4

1 回答 1

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().

由于我rb_class_new_instance()在 SketchUp 的旧样式类中使用了未正确创建的对象,因此绕过了分配功能并且从未触发过。我得到的错误来自 SketchUp,而不是 Ruby。

所以答案是,您可以使用rb_class_new_instance()创建类的新实例,前提是它们没有重载#new方法来进行任何初始化。在 Ruby 1.6 之前,如果 Ruby C 类需要分配数据,这很常见,但从 1.8 开始,应该使用rb_define_alloc_func(). (Matz 在这里这么说:https ://web.archive.org/web/20131003102349/http://www.justskins.com/forums/the-new-allocation-scheme-132572.html#post437362 )

您可以在这篇文章中看到 Ruby 1.6 样式和 1.8 样式之间的区别:https ://web.archive.org/web/20131003102349/http://www.justskins.com/forums/the-new-allocation-scheme- 132572.html#post444948

于 2012-03-30T16:05:56.260 回答