rb_class_new_instance вызывает "ArgumentError: неправильный тип" - почему? - PullRequest
0 голосов
/ 12 марта 2012

Из моего расширения Ruby C я хотел создать новый экземпляр Geom::Vector3d из API Google SketchUp Ruby: 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 );
}

Thisоднако возникла ошибка:

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?

1 Ответ

0 голосов
/ 30 марта 2012

После общения с разработчиками 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().(Матц так говорит здесь: 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

...