创建ruby C ++扩展

时间:2013-12-04 06:37:44

标签: c++ ruby

我使用C ++类创建了一个示例ruby扩展。当我没有解析值时,它工作正常。但是当我解析参数时它显示错误。这是我的代码。

C ++头文件

  #ifndef CIRCLE_H_
  #define CIRCLE_H_

class Circle {
    public:
        Circle(float radius):_radius(radius) {}
        float getArea() { return 3.14159 * _radius * _radius; }

    private:
        float _radius;

};

CPP档案。

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

  VALUE method_test(VALUE y){
   double x= NUM2DBL(y);
   Circle *cir= new Circle(x);
   return DBL2NUM(cir->getArea());
  }

  extern "C" void Init_Test(){
   VALUE lemon = rb_define_module("Test");
   rb_define_method(lemon, "test", (VALUE(*)(ANYARGS))method_test,1);
  }

extconf.rb

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

run.rb

    require 'rubygems'

    require 'Test'

    include Test

    puts test(7)

当我执行run.rb时,它显示错误。

          run.rb:7:in `test': can't convert Object into Integer (TypeError)
          from run.rb:7:in `<main>'

请帮我解决这个问题。谢谢。

1 个答案:

答案 0 :(得分:3)

该行

VALUE method_test(VALUE y) {

应该是

VALUE method_test(VALUE self, VALUE y) {

NUM2INT(y)抛出了错误消息,因为y是代码中脚本的根Object。根对象是你得到的,因为你在模块的顶级混合了你的模块。如果你已经混入了另一个类,那么你将获得该类的实例。

所有原生扩展方法都应该采用self参数(如果您有固定数量的参数,则为第一个参数),这是他们被调用的上下文(Module,{{1} }或Class的实例。当您致电Class时,这就是foo进入扩展程序的方式。当Ruby和C ++都自动执行此操作时可能会出现这种情况(Ruby中为foo.test,C ++中为self):但是由于Ruby内部API,因此必须将this显示为参数。是用C语言编写的,它不直接支持OO - 相反,self中定义的Ruby API要求你编写和使用C函数,这些函数将当前对象的引用作为参数之一。

此外,您正在调用ruby.h - 这是不存在的(尽管编译器可能是善意的,并且会自动强制Circle( int radius ))。您可能希望始终使用x个变量并使用doubleNUM2DBL(y)