Reputation: 2826
I'm trying to wrap the following function to make a C extension.
int dsvd(float **a, int m, int n, float *w, float **v){
//do some things
}
And I have my init, which isn't quite right:
void Init_svd() {
VALUE rb_mSvd = rb_define_module("Svd");
rb_define_method(rb_mSvd, "svd", dsvd, 0);
}
I know I need to wrap dsvd so that I can pass a Value
to rb_define_method
but I can't quite figure out the right way to do it. I tried adapting this answer, but couldn't quite figure it out. Any suggestions?
edit* I also read the Pragmatic Programmer section on C extensions, but that's focused on object creation/allocation. I'm trying to provide a function that performs some transformations and returns a value, so i couldn't make that match up conceptually.
Upvotes: 1
Views: 276
Reputation: 2606
If the integer will fit into a Fixnum, you can use the macro INT2FIX to return a Fixnum value for the integer returned by dsvd(). Otherwise you have to use INT2NUM, which has a function-call overhead (it calls rb_int2inum). Look for these macros in ruby.h for more details.
Edited: Your comment indicates you need a lot more help. You want something like this. I have not compiled this, and it has no checking for argument sanity, but it should get you going). The signature of your method looks like the values passed in the arrays a and v might be changed, and this code does not copy back any changes to the Ruby versions (use rb_ary_store to assign elements).
#include <ruby.h>
#include <ruby/intern.h>
static VALUE rb_mSvd;
static VALUE
rb_svd(VALUE self, VALUE a_array, VALUE m_v, VALUE n_v, VALUE w_v, VALUE v_array)
{
/* Note that there is no checking here for correct types or sane values! */
long a_len = RARRAY_LEN(a_array); /* get the length of first (array) argument */
float* a = (float*)malloc(sizeof(float)*a_len); /* make space for the copies */
int m = NUM2INT(m_v);
int n = NUM2INT(n_v);
float w = NUM2DBL(w_v);
long v_len = RARRAY_LEN(v_array);
float* v = (float*)malloc(sizeof(float)*v_len);
int result;
for (int i = 0; i < a_len; i++)
a[i] = NUM2DBL(rb_ary_entry(a_array, i));
for (int i = 0; i < v_len; i++)
v[i] = NUM2DBL(rb_ary_entry(v_array, i));
result = dsvd(&a, m, n, w, &v);
free(a);
free(v);
return INT2NUM(result);
}
void Init_svd()
{
rb_mSvd = rb_define_module("Svd");
rb_define_method(rb_mSvd, "svd", rb_svd, 5);
}
Upvotes: 3