[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Problem with Math module in extension.

Ernest Ellingson

5/8/2005 4:14:00 AM

I'm trying to do something real simple find the sin of an angle in an
extension. I'm sure you'll recognize the following code as a variation
of the example in Pick Axe 2. I've read README.EXT. Looked at Math.c
been all over the web and I can't seem to figure out the correct way to
do this. Can someone give me a clue?

Ernie
#include "ruby.h"
static int id_push;
static VALUE t_init(VALUE self)
{
VALUE arr;
arr=rb_ary_new();
rb_iv_set(self, "@arr", arr);
return self;
}
static VALUE t_add(VALUE self, VALUE obj)
{
VALUE arr;
VALUE si;
arr=rb_iv_get(self, "@arr");
si=sin(obj);
rb_funcall(arr, id_push,1,si);
return arr;
}

VALUE cTest;
void Init_junk()
{
cTest=rb_define_class("Junk", rb_cObject);
rb_define_method(cTest, "initialize",t_init,0);
rb_define_method(cTest, "add", t_add,1);
Init_Math();
id_push = rb_intern("push");
}
after compiling

require 'junk'
a=Junk.new
a.add(0.75)
puts a => false;
7 Answers

Charles Mills

5/8/2005 4:37:00 AM

0


Ernest Ellingson wrote:
> I'm trying to do something real simple find the sin of an angle in an

> extension. I'm sure you'll recognize the following code as a
variation
> of the example in Pick Axe 2. I've read README.EXT. Looked at
Math.c
> been all over the web and I can't seem to figure out the correct way
to
> do this. Can someone give me a clue?
>
> Ernie
> #include "ruby.h"
> static int id_push;

This should be (int won't work on most/all 64 bit systems):
static ID id_push;

> static VALUE t_init(VALUE self)
> {
> VALUE arr;
> arr=rb_ary_new();
> rb_iv_set(self, "@arr", arr);
> return self;
> }
> static VALUE t_add(VALUE self, VALUE obj)
> {
> VALUE arr;
> VALUE si;
> arr=rb_iv_get(self, "@arr");
> si=sin(obj);

Read the man page for sin. Basically obj is a reference to a Ruby
Object not a double, so you need to go from a Ruby object to a double
here. Best way is
obj = rb_Float(obj);
- or -
obj = rb_convert_type(obj, T_FLOAT, "Float", "to_f");
then you can get treat obj as a T_FLOAT and cast it to a struct RFloat*
and get the value like so:
double sin_of_obj = sin(RFLOAT(obj)->value);

Finally you can create a new float from the result of sin() using
rb_float_new(sin_of_obj).

> rb_funcall(arr, id_push,1,si);
> return arr;
> }
>
> VALUE cTest;
> void Init_junk()
> {
> cTest=rb_define_class("Junk", rb_cObject);
> rb_define_method(cTest, "initialize",t_init,0);
> rb_define_method(cTest, "add", t_add,1);
> Init_Math();
> id_push = rb_intern("push");
> }
> after compiling
>
> require 'junk'
> a=Junk.new
> a.add(0.75)
> puts a => false;

I think all of the errors in your code would be caught be compiler
warnings, perhaps use -Wall / -W.

-Charlie

Ernest Ellingson

5/8/2005 2:30:00 PM

0

Charles Mills wrote:

>
> This should be (int won't work on most/all 64 bit systems):
> static ID id_push;

>
> Read the man page for sin. Basically obj is a reference to a Ruby
> Object not a double, so you need to go from a Ruby object to a double
> here. Best way is
> obj = rb_Float(obj);
Actually this produces an incorrect answer for sin.
> - or -
> obj = rb_convert_type(obj, T_FLOAT, "Float", "to_f");
> then you can get treat obj as a T_FLOAT and cast it to a struct RFloat*
> and get the value like so:
> double sin_of_obj = sin(RFLOAT(obj)->value);
>
> Finally you can create a new float from the result of sin() using
> rb_float_new(sin_of_obj).
This produces the correct answer
> I think all of the errors in your code would be caught be compiler
> warnings, perhaps use -Wall / -W.
>
I'm compiling this on a WindowsXP. and received NO compiler warnings on
my code. Which led to my befuddled state.
> -Charlie
>
Thanks for your help. My confusion resulted from trying to use the Math
module in Ruby. I hadn't seen anything anywhere that describes how
to do this. Looking at Math.c it looks like it returns a VALUE type
(ruby struct or union). What you provided calls the sin function in
math.h. This works fine. I thought I was calling math_sin. If you
look at the Math_init() function it aliases the math_sin function in
Math.c as "sin" with 1 argument. However, (this is where I become
confused) the math_sin function seems to require 2 inputs not one.

Although your solution certainly solves my problem, I'm still confused
about using the math module itself.

Thanks again,
Ernie

George Ogata

5/9/2005 11:10:00 AM

0

Ernest Ellingson <erne@powernav.removethis.com> writes:

> If you look at the Math_init() function it aliases the math_sin
> function in Math.c as "sin" with 1 argument. However, (this is
> where I become confused) the math_sin function seems to require 2
> inputs not one.

In ruby, all functions -- even things that look like static member
functions like Math.sin -- are methods of an object. Math.sin is a
method of the Math object.

Now, whenever you call a C function that's bound to a ruby method, one
parameter is always the receiver of the call -- the "self". Nearly
always, this is the first parameter of the C function.

Combining the above two snippets of knowledge:

To call math_sin() properly, the first argument should be the receiver
of Math.sin: rb_mMath. (If you've looked at the source though, you'll
probably realize that it doesn't really matter what you give as the
first argument since Math.sin has no need to reference it.)



Ernest Ellingson

5/9/2005 3:43:00 PM

0

George Ogata wrote:
> Ernest Ellingson <erne@powernav.removethis.com> writes:
>
>
>>If you look at the Math_init() function it aliases the math_sin
>>function in Math.c as "sin" with 1 argument. However, (this is
>>where I become confused) the math_sin function seems to require 2
>>inputs not one.
>
>
> In ruby, all functions -- even things that look like static member
> functions like Math.sin -- are methods of an object. Math.sin is a
> method of the Math object.
>
> Now, whenever you call a C function that's bound to a ruby method, one
> parameter is always the receiver of the call -- the "self". Nearly
> always, this is the first parameter of the C function.
>
> Combining the above two snippets of knowledge:
>
> To call math_sin() properly, the first argument should be the receiver
> of Math.sin: rb_mMath. (If you've looked at the source though, you'll
> probably realize that it doesn't really matter what you give as the
> first argument since Math.sin has no need to reference it.)
>
>
>
Thanks for the information. I still can't seem to get the syntax right
for calling Math.sin from an extension. I can do fine by calling
sin(RFLOAT(obj)->value). But I'm not calling the Math module. Just how
does one incorporate the Math module.
One of the big problems I have is that I can't find any documentation of
the Math module at
http://www.ruby-doc.org/doxygen/1.8.2/mo...
Can some one give a short description of how you call math_sin from an
extension written in C ?
What are the necessary calls?

Thanks,
Ernie

ts

5/9/2005 3:50:00 PM

0

>>>>> "E" == Ernest Ellingson <erne@powernav.removethis.com> writes:

E> Thanks for the information. I still can't seem to get the syntax right
E> for calling Math.sin from an extension.

svg% cat aa.c
#include <ruby.h>
static ID id_push, id_sin;

static VALUE t_init(VALUE self)
{
VALUE arr;
arr=rb_ary_new();
rb_iv_set(self, "@arr", arr);
return self;
}
static VALUE t_add(VALUE self, VALUE obj)
{
VALUE arr;
VALUE si;
arr=rb_iv_get(self, "@arr");
si = rb_funcall(rb_mMath, id_sin, 1, obj);
rb_funcall(arr, id_push,1,si);
return arr;
}

VALUE cTest;

void Init_aa()
{
cTest=rb_define_class("Junk", rb_cObject);
rb_define_method(cTest, "initialize",t_init,0);
rb_define_method(cTest, "add", t_add,1);
id_push = rb_intern("push");
id_sin = rb_intern("sin");
}

svg%



Guy Decoux


ES

5/9/2005 3:57:00 PM

0

Ernest Ellingson wrote:
> George Ogata wrote:
>
>> Ernest Ellingson <erne@powernav.removethis.com> writes:
>>
>>
>>> If you look at the Math_init() function it aliases the math_sin
>>> function in Math.c as "sin" with 1 argument. However, (this is
>>> where I become confused) the math_sin function seems to require 2
>>> inputs not one.
>>
>>
>>
>> In ruby, all functions -- even things that look like static member
>> functions like Math.sin -- are methods of an object. Math.sin is a
>> method of the Math object.
>>
>> Now, whenever you call a C function that's bound to a ruby method, one
>> parameter is always the receiver of the call -- the "self". Nearly
>> always, this is the first parameter of the C function.
>>
>> Combining the above two snippets of knowledge:
>>
>> To call math_sin() properly, the first argument should be the receiver
>> of Math.sin: rb_mMath. (If you've looked at the source though, you'll
>> probably realize that it doesn't really matter what you give as the
>> first argument since Math.sin has no need to reference it.)
>>
>>
>>
> Thanks for the information. I still can't seem to get the syntax right
> for calling Math.sin from an extension. I can do fine by calling
> sin(RFLOAT(obj)->value). But I'm not calling the Math module. Just how
> does one incorporate the Math module.
> One of the big problems I have is that I can't find any documentation of
> the Math module at
> http://www.ruby-doc.org/doxygen/1.8.2/mo...
> Can some one give a short description of how you call math_sin from an
> extension written in C ?
> What are the necessary calls?

Quickly and untestedly you would do something like

VALUE val = // Value to get sin out of
VALUE mMath = rb_get_const(rb_cObject, rb_intern("Math"));
VALUE res = rb_funcall(mMath, rb_intern("sin"), 1, val);

> Thanks,
> Ernie

E

--
template<typename duck>
void quack(duck& d) { d.quack(); }


Ernest Ellingson

5/9/2005 4:32:00 PM

0

Thanks everyone.
I now know the source of my confusion. Apparently the math module is
loaded with ruby, thus an rb_intern("sin") identifies the math_sin function.

Thanks again.

Ernie