tags:

views:

341

answers:

2

I have a function which compares 2 strings char by char. I needed it to run much faster than it is in Ruby so I used RubyInline to rewrite the function in C. It did increase the speed about 100 fold. The function looks like this:

  require 'inline'

  inline do |builder|
    builder.c "
      static int distance(char *s, char *t){
        ...
      }"
  end

however I need to compare unicode strings. So I decided to use unpack("U*") and compare arrays of integers instead. I cannot figure out from a scanty documentation to RubyInline how to pass the ruby arrays into the function and how to convert them into C arrays. Any help is appreciated!

+3  A: 

This has a good rundown of how to access Ruby objects from C: http://rubycentral.com/pickaxe/ext_ruby.html

inline do |builder|
  builder.c "
    static VALUE some_method(VALUE s) {
      int s_len = RARRAY(s)->len;
      int result = 0;

      VALUE *s_arr = RARRAY(s)->ptr;

      for(i = 0; i < s_len; i++) {
        result += NUM2INT(s_arr[i]); // example of reference
      }

      return INT2NUM(result); // convert C int back into ruby Numeric 
    }"
end

Then in ruby you can just pass values to it like:

object.some_method([1,2,3,4])

Hope this helps you out.

Corban Brook
Thanks Corban, it looks exactly what I need!
dimus
+2  A: 

Given the code from the above answer, here is the code that will work for Ruby 1.8.6 and 1.9.1:

inline do |builder|
  builder.c "
    static VALUE some_method(VALUE s) {
      int s_len = RARRAY_LEN(s);
      int result = 0;
      int i = 0;

      VALUE *s_arr = RARRAY_PTR(s);

      for(i = 0; i < s_len; i++) {
        result += NUM2INT(s_arr[i]); // example of reference
      }

      return INT2NUM(result); // convert C int back into ruby Numeric 
    }"
end

Hope this helps also :)

thnetos
Thanks thnetos, it did fix the problem, I updated the github gist example
dimus