Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Inside-Out Ruby: Using MRI as a C library

Inside-Out Ruby: Using MRI as a C library

Embedding Ruby in C: getting started, tips and tricks.

Avatar for Arthur Pirogovski

Arthur Pirogovski

March 19, 2013
Tweet

More Decks by Arthur Pirogovski

Other Decks in Programming

Transcript

  1. About me And C. segfault(87698) malloc: *** error for object

    0x7fff5dbad6c0: pointer being freed was not allocated *** set a breakpoint in malloc_error_break to debug Abort trap: 6 Вівторок, 19 березня 13 р.
  2. About C concurrency is as good as your programming skills

    are Вівторок, 19 березня 13 р.
  3. About C conc is urrencyaods go amings your program ls

    askilre Вівторок, 19 березня 13 р.
  4. Native Extensions • great speedup • portability problems #ifdef •

    secret concurrency (don’t tell Ruby) Вівторок, 19 березня 13 р.
  5. Strings “much”*10 easier in Ruby than in char ** C

    Вівторок, 19 березня 13 р.
  6. Calling Ruby code - Hey, I’m C! (awkward silence) -

    Hey, I’m Ruby! Вівторок, 19 березня 13 р.
  7. Garbage Collector Very bad one, but still better than none

    Вівторок, 19 березня 13 р.
  8. Well-known APIs VALUE hash = rb_hash_new(); VALUE key = rb_string_new2(“key”);

    VALUE value = INT2FIX(42); rb_hash_aset(hash, key, value); rb_p(hash); Вівторок, 19 березня 13 р.
  9. MVP #ifdef __APPLE__ #define HAVE_STRUCT_TIMESPEC 1 #endif #include <ruby.h> int

    main() { ruby_init(); return 0; } Вівторок, 19 березня 13 р.
  10. MVP #ifdef __APPLE__ #define HAVE_STRUCT_TIMESPEC 1 #endif #include <ruby.h> int

    main() { ruby_init(); ruby_init_loadpath(); return 0; } Вівторок, 19 березня 13 р.
  11. MVP #ifdef __APPLE__ #define HAVE_STRUCT_TIMESPEC 1 #endif #include <ruby.h> int

    main() { ruby_init(); ruby_init_loadpath(); ruby_script("c.rb"); return 0; } Вівторок, 19 березня 13 р.
  12. MVP #ifdef __APPLE__ #define HAVE_STRUCT_TIMESPEC 1 #endif #include <ruby.h> int

    main() { ruby_init(); ruby_init_loadpath(); ruby_script("c.rb"); ruby_finalize(); return 0; } Вівторок, 19 березня 13 р.
  13. MVP #ifdef __APPLE__ #define HAVE_STRUCT_TIMESPEC 1 #endif #include <ruby.h> int

    main() { ruby_init(); ruby_init_loadpath(); ruby_script("c.rb"); VALUE ruby_string = rb_str_new2("Hi,I’m Ruby!"); rb_p(ruby_string); ruby_finalize(); return 0; } Вівторок, 19 березня 13 р.
  14. MVP $ gcc minimal_embedded_ruby.c \ -o meruby -lruby \ -I

    ${MY_RUBY_HOME}/include/ruby-1.9.1 -I ${MY_RUBY_HOME}/include/\ ruby-1.9.1/x86_64-linux \ -L $MY_RUBY_HOME/lib $ ./meruby "Hi from Ruby!" Note: $MY_RUBY_HOME is RVM-specific Вівторок, 19 березня 13 р.
  15. Warning #1 Ruby can only be initialized from the main

    thread Вівторок, 19 березня 13 р.
  16. Warning #2 DO NOT call ruby_run() It intercepts control flow

    and never returns. Вівторок, 19 березня 13 р.
  17. This will SEGFAULT int main() { ruby_init(); ruby_init_loadpath(); ruby_script("c.rb"); VALUE

    ruby_string = rb_str_new2("Hi,I’m Ruby!"); rb_p(ruby_string); rb_gc(); rb_p(ruby_string); /* Right here */ ruby_finalize(); return 0; } Вівторок, 19 березня 13 р.
  18. Registering vars #include <ruby.h> static VALUE ruby_objects; void lo(VALUE ruby_object)

    { rb_hash_aset(ruby_objects, rb_obj_id(ruby_object), ruby_object); } void uo(VALUE ruby_object) { rb_hash_delete(ruby_objects, rb_obj_id(ruby_object)); } Вівторок, 19 березня 13 р.
  19. Registering vars int main() { ruby_init(); ... ruby_objects = rb_hash_new();

    rb_global_variable(&ruby_objects); } Вівторок, 19 березня 13 р.
  20. Registering vars int main() { ruby_init(); ... ruby_objects = rb_hash_new();

    rb_global_variable(&ruby_objects); VALUE ruby_string = rb_str_new2("Hi from Ruby!"); } Вівторок, 19 березня 13 р.
  21. Registering vars int main() { ruby_init(); ... ruby_objects = rb_hash_new();

    rb_global_variable(&ruby_objects); VALUE ruby_string = rb_str_new2("Hi from Ruby!"); lo(ruby_string); rb_p(ruby_string); rb_gc(); } Вівторок, 19 березня 13 р.
  22. Registering vars int main() { ruby_init(); ... ruby_objects = rb_hash_new();

    rb_global_variable(&ruby_objects); VALUE ruby_string = rb_str_new2("Hi from Ruby!"); lo(ruby_string); rb_p(ruby_string); rb_gc(); rb_p(ruby_string); /* No SEGFAULT this time */ uo(ruby_string); ... } Вівторок, 19 березня 13 р.
  23. GC tips call rb_gc() to collect can also be invoked

    by Ruby itself Вівторок, 19 березня 13 р.
  24. GC tips always register variables rb_gc_register_address() is slow, so use

    some data structure Вівторок, 19 березня 13 р.
  25. GC tips run rb_gc() often to detect problems early automatic

    GC can be disabled (dangerous!) Вівторок, 19 березня 13 р.
  26. Exceptions int state = 0; rb_protect( RUBY_METHOD_FUNC(rb_require), (VALUE) “./code.rb”, &state);

    /* We couldn't execute rb_require */ if (state) { rb_p(rb_gv_get("$!")); exit(1); } Вівторок, 19 березня 13 р.
  27. Functions: exporting to Ruby static VALUE method_name_in_c(int argc, VALUE *

    argv, VALUE self) Вівторок, 19 березня 13 р.
  28. Speed For simple tasks, C-based loader is up to 4x

    faster Вівторок, 19 березня 13 р.
  29. Speed But for complex tasks, speed gain is only about

    15% Вівторок, 19 березня 13 р.
  30. Speed Pure C code is up to 15x times faster

    Вівторок, 19 березня 13 р.