Ruby C ++扩展中的多个构造函数

时间:2013-12-09 06:27:33

标签: c++ ruby

我构建了ruby C ++扩展。我在C ++中有多个构造函数。所以我确实创建了几个初始化方法。但它显示错误。 谢谢。

这是我的代码。

C ++头文件

  #ifndef CIRCLE_H_
  #define CIRCLE_H_

class Circle {
    public:
        Circle():_radius(0.0) {}
        Circle(float radius):_radius(radius) {}
        float getArea() { return 3.14159 * _radius * _radius; }
        void setRadius(float radius) { _radius=radius; }
    private:
        float _radius;
};

#endif /* CIRCLE_H_ */

cpp文件

   #include<ruby.h>
   #include"Circle.h"
   #include<iostream>

   using namespace std;

   VALUE classOb;

   template<class Obtype> void delete_objects(Obtype *ptr){//   free pointer
     delete ptr;
   }

   template<class Obtype> VALUE wrap_pointer(VALUE klass,Obtype *ptr){ //wrap c++ object to ruby object
       return Data_Wrap_Struct(klass,0,delete_objects,ptr);
   }

   VALUE alloc_ob(VALUE self){
       return wrap_pointer<Circle>(self,new Circle());//  add c++ object to ruby     object
   }

   VALUE method_initialize(VALUE self,VALUE y){
       double x= NUM2DBL(y);
       Circle *c;
       Data_Get_Struct(self,Circle,c);
       c->setRadius(x);
       return self;
   }

   VALUE method_Initialize(VALUE self){
       .......
       return ;
    }
    ............

    extern "C" void Init_Test(){
    VALUE lemon = rb_define_module("Test");
    classOb= rb_define_class_under(lemon,"Circle",rb_cObject);
    rb_define_alloc_func(classOb,alloc_ob);
    rb_define_method(classOb, "initialize", (VALUE(*)(ANYARGS))method_initialize,0);
        rb_define_method(classOb, "initialize", (VALUE(*)(ANYARGS))method_initialize,1);
    rb_define_method(classOb, "test1", (VALUE(*)(ANYARGS))method_initialize,0);
    }

extconf.rb

   require 'mkmf'
   have_library( 'stdc++' );
   $CFLAGS << " -Wall"
   create_makefile( 'Test' );   

test.rb

  require 'rubygems'
  require '/home/kelum/workspace/Test3/circle/Test'
  include Test
  obj=Circle.new
  obj2=Circle.new(7.1)

发生错误

  Circle.cpp:47:61: error: overloaded function with no contextual type information
  Circle.cpp:48:61: error: overloaded function with no contextual type information

问题是什么?

2 个答案:

答案 0 :(得分:2)

问题是你试图绑定两个构造函数:

    Circle():_radius(0.0) {}
    Circle(float radius):_radius(radius) {}

Ruby没有重载方法,它坚持使用它。

尝试删除默认构造函数并将默认值传递给另一个。

希望它有所帮助。

答案 1 :(得分:2)

你不能有两个initialize方法采用不同的参数,并让Ruby为它们选择它们。这是Ruby的限制,与C ++构造函数的行为不同。从技术上讲,Ruby initialize无论如何都会在构造之后发生 - Ruby已经创建了这个对象,而且没有使用任何参数。

相反,你有两个选择

1)允许initialize采用可变数量的参数,并自行检测不同的可能性。

初始化方法:

VALUE method_initialize( int argc, VALUE* argv, VALUE self ) {
  VALUE y;

  // You'll want to read up on rb_scan_args
  rb_scan_args( argc, argv, "01", &y );

  Circle *c;
  Data_Get_Struct( self, Circle, c );

  // Only set radius if y is not nil
  if ( ! NIL_P( y ) ) {
    c->setRadius( NUM2DBL(y) );
  }

  return self;
}

如何将其绑定到类:

rb_define_method( classOb, "initialize", method_initialize, -1 );

(注意-1,Ruby的信号表明该方法采用了可变数量的参数)

2)使用具有不同名称的“工厂”方法,并自行处理构建新对象。

工厂方法:

VALUE method_from_radius( VALUE self, VALUE y ) {
  double x= NUM2DBL(y);

  volatile VALUE new_circle = alloc_ob( self );

  Circle *c;
  Data_Get_Struct( new_circle, Circle, c);
  c->setRadius(x);

  return new_circle;
}

这种变化也是可能的(也许最接近你的目标):

VALUE method_from_radius( VALUE self, VALUE y ) {
  double x= NUM2DBL(y);
  return wrap_pointer<Circle>(self,new Circle( x ));
}

如何将其绑定到类:

rb_define_singleton_method( classOb, "from_radius", method_from_radius, 1 );

请注意,在Ruby中操作单例方法时,单例方法与实例方法的行为不同。您可能需要extend Test以及include Test