Ruby to C to .so executable

I am trying to revisit something that I’d found on line last September,
but I seem to have misplaced all the pertinent information as to where I
found it. Hopefully someone can point me in the right direction.

In a couple of lines…
i found somewhere on the web a means to convert a ruby script into C
code. Along with instructions on how to compile it into a shared
library ‘.so’, and run it via ruby from the command line.

so… the following script

[email protected]: /media/disk/home/rthompso$ cat simplemail.rb
require ‘rubygems’
require ‘net/smtp’

myMessage = <<END_OF_MESSAGE
From: Mickey M. [email protected]
To: Donald Duck [email protected]
Subject: Contract Negotiations

Don’t let the big guy bully you.
END_OF_MESSAGE

Net::SMTP.start(‘localhost’, 25, ‘localhost.localdomain’) do |smtp|
smtp.send_message myMessage, ‘[email protected]’,
[email protected]
end

was converted to

#include <ruby.h>
#include <node.h>
#include <env.h>
#include <st.h>
extern VALUE ruby_top_self;
static VALUE org_ruby_top_self;
static ID sym[5];
static void init_syms() {
sym[0] = rb_intern(“require”);
sym[1] = rb_intern(“send_message”);
sym[2] = rb_intern(“Net”);
sym[3] = rb_intern(“SMTP”);
sym[4] = rb_intern(“start”);
}
static VALUE global[7];
static void init_globals() {
global[0] = rb_str_new(“rubygems”, 8);
rb_global_variable(&(global[0]));
global[1] = rb_str_new(“net/smtp”, 8);
rb_global_variable(&(global[1]));
global[2] = rb_str_new(“From: Mickey M. [email protected]\nTo:
Donald Duck [email protected]\nSubject: Contract Negotiations\n
\nDon’t let the big guy bully you.\n”, 150);
rb_global_variable(&(global[2]));
global[3] = rb_str_new(“[email protected]”, 22);
rb_global_variable(&(global[3]));
global[4] = rb_str_new(“[email protected]”, 22);
rb_global_variable(&(global[4]));
global[5] = rb_str_new(“localhost”, 9);
rb_global_variable(&(global[5]));
global[6] = rb_str_new(“localhost.localdomain”, 21);
rb_global_variable(&(global[6]));
}
static VALUE const_get(ID id, NODE *cref) {
NODE *cbase = cref;
VALUE result;
while (cbase && cbase->nd_next) {
VALUE klass = cbase->nd_clss;
while (RCLASS(klass)->iv_tbl && st_lookup(RCLASS(klass)->iv_tbl, id,
&result)) {
if (result == Qundef) {
if (!RTEST(rb_autoload_load(klass, id))) break;
continue;
}
return result;
}
cbase = cbase->nd_next;
}
return rb_const_get(cref->nd_clss, id);
}
static void class_module_check(VALUE klass) {
switch (TYPE(klass)) {
case T_CLASS:
case T_MODULE:
break;
default:
rb_raise(rb_eTypeError, “%s is not a class/module”,
RSTRING(rb_obj_as_string(klass))->ptr);
}
}
static VALUE block_1(VALUE bl_val, VALUE closure_ary, VALUE bl_self) {
VALUE res;
VALUE closure = RARRAY(closure_ary)->ptr;
VALUE dvar[1];
rb_mem_clear(dvar, 1);
if (ruby_current_node->nd_state == 1) {
if (RARRAY(bl_val)->len == 0) bl_val = Qnil;
else if (RARRAY(bl_val)->len == 1) bl_val = RARRAY(bl_val)->ptr[0];
}
{
VALUE as_val;
as_val = bl_val;
if (as_val == Qundef) as_val = Qnil;
/
dasgn_curr /
(dvar[0] = as_val);
}
block_redo:
/
call /
/
dvar /
{
VALUE recv = dvar[0];
const int argc = 3;
VALUE argv[3];
/
lvar /
argv[0] = RARRAY(closure[0])->ptr[0];
/
str /
argv[1] = rb_str_new3(global[3]);
/
str /
argv[2] = rb_str_new3(global[4]);
res = rb_funcall3(recv, sym[1] /
send_message /, argc, argv);
}
return res;
}
static VALUE iterate_1(VALUE data) {
VALUE iter_data = (VALUE)data;
ruby_top_self = org_ruby_top_self;
if (iter_data[0]) return Qundef;
iter_data[0] = Qtrue;
return rb_funcall3((VALUE)(iter_data[1]), sym[4] /
start /,
(int)(iter_data[2]), (VALUE
)(iter_data[3]));
}
static void toplevel_scope_1(VALUE self, NODE *cref) {
VALUE res;
VALUE my_closure_ary;
VALUE lvar;
VALUE lvar_ary = rb_ary_new2(1);
rb_mem_clear(RARRAY(lvar_ary)->ptr, 1);
RARRAY(lvar_ary)->len = 1;
lvar = RARRAY(lvar_ary)->ptr;
my_closure_ary = rb_ary_new2(1);
RARRAY(my_closure_ary)->ptr[0] = lvar_ary;
RARRAY(my_closure_ary)->len = 1;
/
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] /
require /, argc, argv);
}
/
fcall /
{
VALUE recv = self;
const int argc = 1;
VALUE argv[1];
/
str /
argv[0] = rb_str_new3(global[1]);
res = rb_funcall2(recv, sym[0] /
require /, argc, argv);
}
/
lasgn /
/
str /
(lvar[0] = rb_str_new3(global[2]));
/
iter /
do {
/
colon2 /
{
VALUE tmp_class;
/
const /
tmp_class = const_get(sym[2] /
Net /, cref);
class_module_check(tmp_class);
res = rb_const_get_from(tmp_class, sym[3] /
SMTP /);
}
{
VALUE recv = res;
const int argc = 3;
VALUE argv[3];
/
str /
argv[0] = rb_str_new3(global[5]);
/
lit /
argv[1] = LONG2FIX(25);
/
str */
argv[2] = rb_str_new3(global[6]);
{
VALUE iter_data[4];
iter_data[0] = Qfalse;
iter_data[1] = (VALUE)(recv);
iter_data[2] = (VALUE)(argc);
iter_data[3] = (VALUE)(argv);
ruby_top_self = Qundef;
res = rb_iterate(iterate_1, (VALUE)iter_data, block_1, my_closure_ary);
}
}
}
while (res == Qundef);
}
void Init_simplemail() {
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);
}

which was then compiled to simplemail.so for execution.

Can anyone point me to where I might have referenced this from?

Thanks
reid

On Tue, 2007-08-14 at 03:15 +0900, Reid T. wrote:

I am trying to revisit something that I’d found on line last September,
but I seem to have misplaced all the pertinent information as to where I
found it. Hopefully someone can point me in the right direction.

In a couple of lines…
i found somewhere on the web a means to convert a ruby script into C
code. Along with instructions on how to compile it into a shared
library ‘.so’, and run it via ruby from the command line.

Found it – ruby2cext