Created
December 30, 2014 11:25
-
-
Save Youka/41f2be9ce51c9703b845 to your computer and use it in GitHub Desktop.
Execute & bind Ruby by LuaJIT
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Load foreign functions interface | |
local ffi = require("ffi") | |
-- Load Ruby library & define function headers | |
local ruby = ffi.load("msvcrt-ruby210") | |
ffi.cdef([[ | |
typedef uintptr_t RUBY_VALUE; | |
enum{ | |
RUBY_Qfalse = 0, | |
RUBY_Qtrue = 2, | |
RUBY_Qnil = 4 | |
}; | |
enum{ | |
RUBY_T_STRING = 0x05, | |
RUBY_T_MASK = 0x1f, | |
RUBY_IMMEDIATE_MASK = 0x03, | |
RUBY_RSTRING_NOEMBED = 1 << 13 | |
}; | |
typedef struct{ | |
RUBY_VALUE flags; | |
const RUBY_VALUE klass; | |
}RBasic; | |
typedef struct{ | |
RBasic basic; | |
union{ | |
struct{ | |
long len; | |
char *ptr; | |
}heap; | |
char ary[sizeof(RUBY_VALUE)*3/sizeof(char)]; | |
}as; | |
}RString; | |
int ruby_setup(void); | |
RUBY_VALUE rb_define_module(const char*); | |
void rb_define_module_function(RUBY_VALUE, const char*, void*, int); | |
void* ruby_options(int, char**); | |
int ruby_run_node(void*); | |
]]) | |
-- Test data | |
local args = {"-v", "test.rb"} | |
-- Lua load in Ruby | |
local function eval_str(mod, x) | |
local band = bit.band | |
if x == ffi.C.RUBY_Qnil or x == ffi.C.RUBY_Qfalse or | |
band(x, ffi.C.RUBY_IMMEDIATE_MASK) ~= 0 or | |
band(ffi.cast("RBasic*", x)[0].flags, ffi.C.RUBY_T_MASK) ~= ffi.C.RUBY_T_STRING then | |
error("String expected", 1) | |
end | |
local code = band(ffi.cast("RBasic*", x)[0].flags, ffi.C.RUBY_RSTRING_NOEMBED) ~= 0 and | |
load(ffi.string(ffi.cast("RString*", x)[0].as.heap.ptr)) or | |
load(ffi.string(ffi.cast("RString*", x)[0].as.ary)) | |
return code and (code() and ffi.C.RUBY_Qtrue or ffi.C.RUBY_Qfalse) or ffi.C.RUBY_Qnil | |
end | |
-- Initialize Ruby | |
if ruby.ruby_setup() == 0 then | |
-- Extend Ruby environment | |
local ruby_module_lua = ruby.rb_define_module("Lua") | |
ruby.rb_define_module_function(ruby_module_lua, "eval_str", ffi.cast("RUBY_VALUE(*)(RUBY_VALUE, RUBY_VALUE)", eval_str), 1) | |
-- Build Ruby options | |
local args_n = #args | |
local options = ffi.new("char*[?]", 1 + args_n) | |
options[0] = ffi.cast("char*", "rubylua") | |
for i=1, args_n do | |
options[i] = ffi.cast("char*", args[i]) | |
end | |
-- Run Ruby with options | |
local status = ruby.ruby_run_node(ruby.ruby_options(1 + args_n, options)) | |
if status ~= 0 then | |
error("Ruby error code: " .. status) | |
end | |
else | |
error("Couldn't setup Ruby!") | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
puts Lua::eval_str "print(\"Hello from Lua in Ruby!\")" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment