创建ruby C ++扩展 [英] creating ruby C++ extension

查看:187
本文介绍了创建ruby C ++扩展的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



C ++头文件

  #ifndef CIRCLE_H_ 
#define CIRCLE_H_

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

private:
float _radius;

};

CPP档案。

 #include< ruby​​.h> 
#includeCircle.h

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

externCvoid 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'

要求'Test'

包括测试

puts test(7)



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

  run.rb:7:in`test':无法将对象转换为Integer(TypeError)
from run.rb:7:in`& $ b

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

解决方案

  VALUE method_test(VALUE y){

应为

  VALUE method_test(VALUE self,VALUE y){

NUM2INT(y)引发错误消息,因为 y 是根 Object 。根对象是你得到的,因为你在模块中混合在脚本的顶层。如果你混入了另一个类,你会得到一个类的实例。



所有本机扩展方法都需要一个 self 参数(如果有固定数量的参数,是它们被调用的上下文(模块)。当你调用 foo.test 时,它是如何让 foo 当Ruby和C ++自动完成这一操作时,这可能看起来很奇怪(在C ++中, self ,而在C ++中 this 有必要使 self 显示为param,因为Ruby内部API是用C语言编写的,它不直接支持OO,而是在 ruby​​.h 希望您编写并使用将当前对象的引用作为参数之一的C函数。



正在调用 Circle(int radius) - 它不存在(虽然编译器可能是kind和coerce x 为你自动)。您可能想要使用 double 变量并使用 NUM2DBL(y) DBL2NUM - > getArea())


I created a sample ruby extension using C++ class. it works fine when i did not parse the value. but when i parse parameter it show an error. here is my code.

C++ header file

  #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 file.

  #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)

when i execute run.rb it shows an error.

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

please help me to solve this problem. thank you.

解决方案

The line

VALUE method_test(VALUE y) {

Should be

VALUE method_test(VALUE self, VALUE y) {

The error message is thrown by NUM2INT(y) because y is the root Object of the script in your code as-is. The root object is what you got because you mixed in your module at the top level of the script. If you had mixed in to another class, you would have got an instance of that class instead.

All native extension methods should take a self parameter (the first one if you have fixed number of params) which is the context that they are being called in (a Module, Class or instance of a Class). It is how you get foo into the extension when you call foo.test. This might seem odd when both Ruby and C++ do this automatically (self in Ruby, and this in C++): However it is necessary to have self appear as param because the Ruby internal API is written in C, which does not support OO directly - instead the Ruby API defined in ruby.h expects you to write and use C functions that take references to the current object as one of the params.

In addition you are making a call to Circle( int radius ) - which does not exist (although the compiler may be kind and coerce x for you automatically). You probably want to use double variables throughout and use NUM2DBL(y) and DBL2NUM( cir->getArea() )

这篇关于创建ruby C ++扩展的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆