Problem with Math module in extension

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;

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

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

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

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

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/modules.html
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

Thanks for the information. I still can't seem to get the syntax right
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

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/modules.html
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(); }