创建ruby C ++扩展
我使用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 #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 `'
请帮我解决这个问题。 谢谢。
这条线
VALUE method_test(VALUE y) {
应该
VALUE method_test(VALUE self, VALUE y) {
NUM2INT(y)
抛出错误消息,因为y
是代码中脚本的根Object
。 根对象就是你得到的,因为你在你的模块中混合了脚本的顶层。 如果你已经混入了另一个类,那么你将获得该类的实例。
所有本机扩展方法都应该使用一个self
参数(如果你有固定数量的params,则为第一个),这是它们被调用的上下文( Module
, Class
或Class
实例)。 当你调用foo.test
时,你是如何进入扩展的。 当Ruby和C ++都自动执行此操作时,这可能看起来很奇怪(在Ruby中self
, this
在C ++中):然而,由于Ruby内部API是用C语言编写的,因此必须将self
作为参数出现,而C语言不直接支持OO -相反, ruby.h
定义的Ruby API ruby.h
您编写和使用C函数,这些函数将对当前对象的引用作为其中一个参数。
此外,您正在调用Circle( int radius )
– 这是不存在的(尽管编译器可能是善意的并且会自动强制x
)。 您可能希望始终使用double
变量并使用NUM2DBL(y)
和DBL2NUM( cir->getArea() )