5

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
  • No problem, let me know how it turns out. Would love to see your implementation when done. Commented Jul 13, 2009 at 17:38
  • Here is the code of damerau_levenshtein distance: gist.github.com/147023 For ruby 1.8.7 works like a charm, but chokes on ruby 1.9.1 Commented Jul 14, 2009 at 15:51
  • I updated gist.github.com/147023 to work with 1.9.1 ruby as well using help from thnetos Commented Jul 15, 2009 at 21:30

2 Answers 2

9

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks Corban, it looks exactly what I need!
4

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

1 Comment

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.