From: Dominik Bathon Date: 2006-08-02T06:38:50+09:00 Subject: Re: converting some autogenerated ruby code to C On Tue, 01 Aug 2006 01:40:52 +0200, Eric Mahurin wrote: > Unfortunately this won't work. In the above example, I just threw > something arbitrary together. I have something where the string that > #tester generates isn't determined until runtime and is dependent on > the object hierarchy. That's what I thought and I meant that you should generate the code at runtime and then compile that code and load the new C extension at runtime. Maybe you could cache it to save the actual C compiling if the same code has been compiled before, this probably could be done using RubyInline. Ruby2CExtension can be used without rb2cx. There is an API, though it is not documented and it might change in the future ;-) A small example: $ irb -r ruby2cext irb(main):001:0> puts Ruby2CExtension::Compiler::compile_ruby_to_c("puts __FILE__", "extension_name", "file_name.rb") #include #include #include #include extern VALUE ruby_top_self; static VALUE org_ruby_top_self; static ID sym[1]; static void init_syms() { sym[0] = rb_intern("puts"); } static VALUE global[1]; static void init_globals() { global[0] = rb_str_new("file_name.rb", 12); rb_global_variable(&(global[0])); } static void toplevel_scope_1(VALUE self, NODE *cref) { VALUE res; /* block */ /* fcall */ { VALUE recv = self; const int argc = 1; VALUE argv[1]; /* str */ argv[0] = rb_str_new3(global[0]); res = rb_funcall2(recv, sym[0] /* puts */, argc, argv); } } void Init_extension_name() { org_ruby_top_self = ruby_top_self; rb_global_variable(&org_ruby_top_self); init_syms(); init_globals(); NODE *cref = rb_node_newnode(NODE_CREF, rb_cObject, 0, 0); toplevel_scope_1(ruby_top_self, cref); } (The actual code returned by compile_ruby_to_c will not be indented, if have indented it manually for clarity) > In my code the methods are named scan/scanner > instead of test/tester. I use this mechanism for making > macros/flattening methods. My parsers (the #scan method) end up being > one giant expression (if there is no recursion). I'm flattening to > get rid of as much of the method calling overhead as I can. > > It still should be possible to load a C extension into a meta-class, > right? Wouldn't the Init_* function just define the method in the > meta-class instead of a plain class? Maybe you'd use a temp global > variable to pass this meta-class. I realize caching these so that you > don't have to recompile could be an issue. You could use md5 or > whatever (even string length) to get a mostly unique identifier for > the c/so (like rubyinline). >