# Ruby to C to .so executable

**URL:** <https://www.ruby-forum.com/t/ruby-to-c-to-so-executable/111952>\
**Category:** Ruby\
**Created:** [August 13, 2007, 8:18pm UTC](https://www.ruby-forum.com/t/ruby-to-c-to-so-executable/111952 "2007-08-13T20:18:45Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![lycanthrope](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/a88e57/32.png) [@lycanthrope](https://www.ruby-forum.com/u/lycanthrope)\
**Post date:** [August 13, 2007, 8:18pm UTC](https://www.ruby-forum.com/t/ruby-to-c-to-so-executable/111952/1 "2007-08-13T20:18:45Z")

</div>

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

rthompso@jhereg: /media/disk/home/rthompso$ cat simplemail.rb  
require ‘rubygems’  
require ‘net/smtp’

myMessage = \<\<END\_OF\_MESSAGE  
From: Mickey M. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
To: Donald Duck [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
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, ‘removed\_email\_address@domain.invalid’,  
‘removed\_email\_address@domain.invalid’  
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. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)\nTo:  
Donald Duck [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)\nSubject: Contract Negotiations\n  
\nDon’t let the big guy bully you.\n”, 150);  
rb\_global\_variable(&(global[2]));  
global[3] = rb\_str\_new(“removed\_email\_address@domain.invalid”, 22);  
rb\_global\_variable(&(global[3]));  
global[4] = rb\_str\_new(“removed\_email\_address@domain.invalid”, 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

---

<div class="post-metadata">

**Author:** ![lycanthrope](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/a88e57/32.png) [@lycanthrope](https://www.ruby-forum.com/u/lycanthrope)\
**Post date:** [August 13, 2007, 8:52pm UTC](https://www.ruby-forum.com/t/ruby-to-c-to-so-executable/111952/2 "2007-08-13T20:52:48Z")

</div>

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
