├── ebin └── erl.app ├── .gitignore ├── include ├── lua.hrl └── lua_api.hrl ├── src ├── lua_driver.erl ├── lual.erl ├── lua_erl.erl └── lua.erl ├── Rakefile ├── c_src ├── Rakefile ├── lua_drv.h ├── lua_drv.c ├── commands.h └── commands.c ├── README.markdown └── tests └── lua_test.erl /ebin/erl.app: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.beam 2 | *.so -------------------------------------------------------------------------------- /include/lua.hrl: -------------------------------------------------------------------------------- 1 | -record(lua, {port}). 2 | 3 | -define(STD_TIMEOUT, 100). -------------------------------------------------------------------------------- /src/lua_driver.erl: -------------------------------------------------------------------------------- 1 | -module(lua_driver). 2 | 3 | -export([open/0, close/1]). 4 | 5 | -include("lua.hrl"). 6 | 7 | open() -> 8 | {ok, L} = load_driver(), 9 | #lua{port=L}. 10 | 11 | close(#lua{port=Port}) -> 12 | port_close(Port). 13 | 14 | 15 | %% Private functions 16 | load_driver() -> 17 | SearchDir = filename:join([filename:dirname(code:which(lua_driver)), "..", "priv"]), 18 | case erl_ddll:load(SearchDir, "lua_drv") of 19 | ok -> 20 | {ok, open_port({spawn, 'lua_drv'}, [binary])}; 21 | Error -> 22 | Error 23 | end. 24 | -------------------------------------------------------------------------------- /src/lual.erl: -------------------------------------------------------------------------------- 1 | -module(lual). 2 | 3 | -export([dostring/2]). 4 | 5 | -include("lua.hrl"). 6 | -include("lua_api.hrl"). 7 | 8 | dostring(#lua{port=Port}, Code) -> 9 | port_command(Port, term_to_binary({?ERL_LUAL_DOSTRING, Code})), 10 | recieve_simple_response(). 11 | 12 | recieve_simple_response() -> 13 | receive 14 | ok -> 15 | ok; 16 | error -> 17 | {error, lua_error}; 18 | {error, Reason} -> 19 | {error, Reason}; 20 | Other -> 21 | {other, Other} 22 | after ?STD_TIMEOUT -> 23 | {error, timeout} 24 | end. -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | task :default => [:make_c, :make_erl] 2 | 3 | task :test => [:default, :make_tests] do 4 | sh "erl -pa ebin -noshell -s lua_test test -s init stop" 5 | end 6 | 7 | task :clean do 8 | print "Cleaning..." 9 | sh "rm ebin/*.beam" 10 | sh "rm priv/*.so" 11 | print " done\n" 12 | end 13 | 14 | task :make_c do 15 | sh "(cd c_src; rake compile)" 16 | end 17 | 18 | task :make_erl do 19 | print "Compiling Erlang sources..." 20 | sh "erlc -Iinclude/ -o ebin/ src/*.erl" 21 | print " done\n" 22 | end 23 | 24 | task :make_tests => :default do 25 | print "Compiling Erlang test sources..." 26 | sh "erlc -Iinclude/ -o ebin/ tests/*.erl" 27 | print " done\n" 28 | end 29 | 30 | task :run do 31 | sh "erl -pa ebin" 32 | end -------------------------------------------------------------------------------- /c_src/Rakefile: -------------------------------------------------------------------------------- 1 | CFLAGS = "-I /usr/local/lib/erlang/erts-5.7/include -I /usr/local/lib/erlang/lib/erl_interface-3.6/include -fPIC -g -O2 -Wall" 2 | if ENV['platform'] == 'linux' 3 | LDFLAGS = "-shared" 4 | else 5 | LDFLAGS = "-dynamic -bundle -undefined suppress -flat_namespace" 6 | end 7 | EXTLIBS = "/usr/local/lib/erlang/lib/erl_interface-3.6/lib/libei.a /usr/local/lib/liblua.a" 8 | 9 | FILES = ["commands", "lua_drv"] 10 | 11 | desc "Compile driver to a shared lib" 12 | task :compile => ["../priv/lua_drv.so"] 13 | 14 | FILES.each do |f| 15 | file "#{f}.o" => ["#{f}.c"] do 16 | # puts "gcc #{CFLAGS} -c -o #{f}.o #{f}.c" 17 | sh "gcc #{CFLAGS} -c -o #{f}.o #{f}.c" 18 | end 19 | end 20 | 21 | file "../priv/lua_drv.so" => FILES.map {|f| "#{f}.o"} do 22 | sh "mkdir -p ../priv" 23 | # puts "gcc #{CFLAGS} #{LDFLAGS} -o ../priv/lua_drv.so #{FILES.join('.o ')}.o #{EXTLIBS}" 24 | print "Compiling lua_drv.so..." 25 | sh "gcc #{CFLAGS} #{LDFLAGS} -o ../priv/lua_drv.so #{FILES.join('.o ')}.o #{EXTLIBS}" 26 | print " done\n" 27 | sh "rm #{FILES.join('.o ')}.o" 28 | end 29 | 30 | task :clean do 31 | sh "rm ../priv/*.so" 32 | end 33 | -------------------------------------------------------------------------------- /src/lua_erl.erl: -------------------------------------------------------------------------------- 1 | -module(lua_erl). 2 | 3 | -export([call/3, call/4]). 4 | 5 | -include("lua.hrl"). 6 | -include("lua_api.hrl"). 7 | 8 | call(L, Func, Args) -> 9 | call(L, Func, Args, 1). 10 | 11 | call(L, Func, Args, Returns) when is_atom(Func) -> 12 | call(L, atom_to_list(Func), Args, Returns); 13 | call(L, Func, Args, Returns) when is_list(Args) -> 14 | [FirstFunc | FuncList] = string:tokens(Func, "."), 15 | lua:getfield(L, global, FirstFunc), 16 | lists:foreach(fun(F) -> 17 | lua:getfield(L, -1, F), 18 | lua:remove(L, -2) 19 | end, FuncList), 20 | lists:foreach(fun(Arg) -> 21 | push(L, Arg) 22 | end, Args), 23 | lua:call(L, length(Args), Returns), 24 | list_to_tuple(lists:map(fun(I) -> 25 | R = case lua:type(L, -I) of 26 | {ok, ?LUA_TNIL} -> 27 | nil; 28 | {ok, ?LUA_TNUMBER} -> 29 | {ok, N} = lua:tonumber(L, -I), 30 | N; 31 | {ok, ?LUA_TSTRING} -> 32 | {ok, S} = lua:tolstring(L, -I), 33 | S 34 | end, 35 | lua:remove(L, -I), 36 | R 37 | end, lists:seq(Returns, 1, -1))). 38 | 39 | push(L, Value) when is_number(Value) -> 40 | lua:pushnumber(L, Value); 41 | push(L, Value) when is_list(Value) -> 42 | lua:pushstring(L, Value). -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | Erl-Lua is a library for embedding Lua into Erlang. It provides a simple interface that is very similar to the Lua C API. In the future it will also include a higher level API to simplify things further. 2 | 3 | WARNING: This is definitely not fully tested. Still a bunch of work to be done. If you are careful though, it should be pretty stable (no promises though). 4 | 5 | Example: 6 | 7 | {ok, L} = lua:new_state(). 8 | lua:getfield(L, global, "print"). 9 | lua:pushstring(L, "Hello from Lua!"). 10 | lua:call(L, 1, 0). 11 | % (Lua) => Hello from Lua! 12 | 13 | lua:getfield(L, global, "type"). 14 | lua:pushnumber(L, 23). 15 | lua:call(L, 1, 1). 16 | {ok, S} = lua:tolstring(L, 1). 17 | lua:remove(L, 1). % always rebalance the stack.. it is the right thing to do! 18 | S. % => "number" 19 | 20 | For more examples, see the tests. 21 | 22 | There is also a simple way to run one off simple Lua code snippets: 23 | 24 | (continued from above) 25 | lual:dostring(L, "print 'Howdy!'"). 26 | % (Lua) => Howdy! 27 | 28 | **NEW Higher Level API** 29 | 30 | *call* (lua\_state L, (atom|string) function\_name, list arguments, [int num\_returned]) - Call a Lua function and return the values. 31 | 32 | 1> {ok, L} = lua:new_state(). 33 | 2> lua_erl:call(L, type, [23], 1). 34 | {"number"} 35 | 3> lual:dostring(L, "function add(a, b, c) return a + b + c end"). 36 | 4> lua_erl:call(L, add, [2, 3, 4], 1). 37 | {9} 38 | 39 | The strange 4th arg is the number of values the function can return (since in Lua you can return multiple things). 40 | If the number of returned values is 1, the argument can be left off.. therefore both of the above could be rewritten: 41 | 42 | lua_erl:call(L, type, [23]). 43 | lua_erl:call(L, add, [2, 3, 4]). -------------------------------------------------------------------------------- /c_src/lua_drv.h: -------------------------------------------------------------------------------- 1 | typedef struct _lua_drv_t { 2 | ErlDrvPort port; 3 | lua_State *L; 4 | } lua_drv_t; 5 | 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | /* Fix a silly Lua warning */ 12 | 13 | void luaL_openlibs (lua_State *L); 14 | 15 | /* Commands */ 16 | 17 | void erl_lua_call(lua_drv_t *driver_data, char *buf, int index); 18 | void erl_lua_concat(lua_drv_t *driver_data, char *buf, int index); 19 | void erl_lua_getfield (lua_drv_t *driver_data, char *buf, int index); 20 | void erl_lua_getglobal(lua_drv_t *driver_data, char *buf, int index); 21 | void erl_lua_gettop(lua_drv_t *driver_data, char *buf, int index); 22 | void erl_lua_pushboolean(lua_drv_t *driver_data, char *buf, int index); 23 | void erl_lua_pushinteger(lua_drv_t *driver_data, char *buf, int index); 24 | void erl_lua_pushstring(lua_drv_t *driver_data, char *buf, int index); 25 | void erl_lua_pushnil(lua_drv_t *driver_data, char *buf, int index); 26 | void erl_lua_pushnumber(lua_drv_t *driver_data, char *buf, int index); 27 | void erl_lua_remove(lua_drv_t *driver_data, char *buf, int index); 28 | void erl_lua_setfield(lua_drv_t *driver_data, char *buf, int index); 29 | void erl_lua_setglobal(lua_drv_t *driver_data, char *buf, int index); 30 | void erl_lua_toboolean(lua_drv_t *driver_data, char *buf, int index); 31 | void erl_lua_tointeger(lua_drv_t *driver_data, char *buf, int index); 32 | void erl_lua_tolstring(lua_drv_t *driver_data, char *buf, int index); 33 | void erl_lua_tonumber(lua_drv_t *driver_data, char *buf, int index); 34 | void erl_lua_type(lua_drv_t *driver_data, char *buf, int index); 35 | 36 | void erl_lual_dostring (lua_drv_t *driver_data, char *buf, int index); 37 | 38 | void erl_lua_no_command (lua_drv_t *driver_data); 39 | 40 | #ifdef __cplusplus 41 | } 42 | #endif /* __cplusplus */ 43 | -------------------------------------------------------------------------------- /tests/lua_test.erl: -------------------------------------------------------------------------------- 1 | -module(lua_test). 2 | 3 | -include_lib("eunit/include/eunit.hrl"). 4 | 5 | small_integer_test() -> 6 | push_to_helper(1, pushinteger, tointeger). 7 | 8 | zero_integer_test() -> 9 | push_to_helper(0, pushinteger, tointeger). 10 | 11 | small_negative_integer_test() -> 12 | push_to_helper(-2, pushinteger, tointeger). 13 | 14 | 15 | small_number_test() -> 16 | push_to_helper(2, pushnumber, tonumber). 17 | 18 | small_negative_number_test() -> 19 | push_to_helper(-2, pushnumber, tonumber). 20 | 21 | zero_number_test() -> 22 | push_to_helper(0, pushnumber, tonumber). 23 | 24 | big_number_test() -> 25 | push_to_helper(5000000000, pushnumber, tonumber). 26 | 27 | big_floating_number_test() -> 28 | push_to_helper(5000000000.234, pushnumber, tonumber). 29 | 30 | big_negative_number_test() -> 31 | push_to_helper(-5000000000, pushnumber, tonumber). 32 | 33 | big_negative_float_number_test() -> 34 | push_to_helper(-5000000000.234, pushnumber, tonumber). 35 | 36 | 37 | string_test() -> 38 | push_to_helper("testing", pushstring, tolstring). 39 | 40 | 41 | call_test() -> 42 | {ok, L} = lua:new_state(), 43 | ?assertMatch(ok, lua:getfield(L, global, "type")), 44 | ?assertMatch(ok, lua:pushnumber(L, 1)), 45 | ?assertMatch(ok, lua:call(L, 1, 1)), 46 | ?assertMatch({ok, "number"}, lua:tolstring(L, 1)). 47 | 48 | set_get_global_test() -> 49 | {ok, L} = lua:new_state(), 50 | ?assertMatch(ok, lua:pushnumber(L, 23)), 51 | ?assertMatch(ok, lua:setfield(L, global, "foo")), 52 | ?assertMatch(ok, lua:getfield(L, global, "foo")), 53 | ?assertMatch({ok, 23}, lua:tonumber(L, 1)). 54 | 55 | 56 | push_to_helper(Val, Push, To) -> 57 | {ok, L} = lua:new_state(), 58 | ?assertMatch(ok, lua:Push(L, Val)), 59 | ?assertMatch({ok, Val}, lua:To(L, 1)). -------------------------------------------------------------------------------- /src/lua.erl: -------------------------------------------------------------------------------- 1 | -module(lua). 2 | 3 | -export([new_state/0, 4 | close/1, 5 | call/3, 6 | concat/2, 7 | getfield/3, 8 | getglobal/2, 9 | gettop/1, 10 | pushboolean/2, 11 | pushinteger/2, 12 | pushstring/2, 13 | pushnil/1, 14 | pushnumber/2, 15 | remove/2, 16 | setfield/3, 17 | setglobal/2, 18 | toboolean/2, 19 | tointeger/2, 20 | tolstring/2, 21 | tonumber/2, 22 | type/2]). 23 | 24 | -include("lua.hrl"). 25 | -include("lua_api.hrl"). 26 | 27 | new_state() -> 28 | {ok, lua_driver:open()}. 29 | 30 | close(L) -> 31 | lua_driver:close(L). 32 | 33 | call(L, Args, Results) -> 34 | command(L, {?ERL_LUA_CALL, Args, Results}), 35 | receive_simple_response(). 36 | 37 | concat(L, N) -> 38 | command(L, {?ERL_LUA_CONCAT, N}). 39 | 40 | getfield(L, global, Name) -> 41 | getglobal(L, Name); 42 | getfield(L, Index, Name) -> 43 | command(L, {?ERL_LUA_GETFIELD, Index, Name}), 44 | receive_simple_response(). 45 | 46 | getglobal(L, Name) -> 47 | command(L, {?ERL_LUA_GETGLOBAL, Name}), 48 | receive_simple_response(). 49 | 50 | gettop(L) -> 51 | command(L, {?ERL_LUA_GETTOP}), 52 | receive_valued_response(). 53 | 54 | 55 | pushboolean(L, Bool) -> 56 | command(L, {?ERL_LUA_PUSHBOOLEAN, Bool}), 57 | receive_simple_response(). 58 | 59 | pushinteger(L, Int) when is_integer(Int) -> 60 | command(L, {?ERL_LUA_PUSHINTEGER, Int}), 61 | receive_simple_response(). 62 | 63 | pushstring(L, String) when is_list(String) -> 64 | command(L, {?ERL_LUA_PUSHSTRING, String}), 65 | receive_simple_response(). 66 | 67 | pushnil(L) -> 68 | command(L, {?ERL_LUA_PUSHNIL}), 69 | receive_simple_response(). 70 | 71 | pushnumber(L, Num) when is_number(Num) -> 72 | command(L, {?ERL_LUA_PUSHNUMBER, Num}), 73 | receive_simple_response(). 74 | 75 | remove(L, Index) -> 76 | command(L, {?ERL_LUA_REMOVE, Index}), 77 | receive_simple_response(). 78 | 79 | setfield(L, global, Name) -> 80 | setglobal(L, Name); 81 | setfield(L, Index, Name) -> 82 | command(L, {?ERL_LUA_SETFIELD, Index, Name}), 83 | receive_simple_response(). 84 | 85 | setglobal(L, Name) -> 86 | command(L, {?ERL_LUA_SETGLOBAL, Name}), 87 | receive_simple_response(). 88 | 89 | toboolean(L, Index) -> 90 | command(L, {?ERL_LUA_TOBOOLEAN, Index}), 91 | receive_valued_response(). 92 | 93 | tointeger(L, Index) -> 94 | command(L, {?ERL_LUA_TOINTEGER, Index}), 95 | receive_valued_response(). 96 | 97 | tolstring(L, Index) -> 98 | command(L, {?ERL_LUA_TOLSTRING, Index}), 99 | receive_valued_response(). 100 | 101 | tonumber(L, Index) -> 102 | command(L, {?ERL_LUA_TONUMBER, Index}), 103 | {ok, Value} = receive_valued_response(), 104 | Value2 = list_to_binary(Value), 105 | {ok, binary_to_term(Value2)}. 106 | 107 | type(L, Index) -> 108 | command(L, {?ERL_LUA_TYPE, Index}), 109 | receive_valued_response(). 110 | 111 | 112 | command(#lua{port=Port}, Data) -> 113 | port_command(Port, term_to_binary(Data)). 114 | 115 | receive_simple_response() -> 116 | receive 117 | ok -> 118 | ok; 119 | error -> 120 | {error, lua_error}; 121 | {error, Reason} -> 122 | {error, Reason}; 123 | Other -> 124 | {other, Other} 125 | after ?STD_TIMEOUT -> 126 | {error, timeout} 127 | end. 128 | 129 | receive_valued_response() -> 130 | receive 131 | {ok, Str} -> 132 | {ok, Str}; 133 | error -> 134 | {error, lua_error}; 135 | Other -> 136 | {other, Other} 137 | after ?STD_TIMEOUT -> 138 | {error, timeout} 139 | end. -------------------------------------------------------------------------------- /c_src/lua_drv.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "lua_drv.h" 9 | #include "commands.h" 10 | 11 | static ErlDrvData start (ErlDrvPort port, char* cmd); 12 | static void stop (ErlDrvData handle); 13 | static void process (ErlDrvData handle, ErlIOVec *ev); 14 | 15 | static ErlDrvEntry lua_driver_entry = { 16 | NULL, /* init */ 17 | start, /* startup */ 18 | stop, /* shutdown */ 19 | NULL, /* output */ 20 | NULL, /* ready_input */ 21 | NULL, /* ready_output */ 22 | "lua_drv", /* the name of the driver */ 23 | NULL, /* finish */ 24 | NULL, /* handle */ 25 | NULL, /* control */ 26 | NULL, /* timeout */ 27 | process, /* process */ 28 | NULL, /* ready_async */ 29 | NULL, /* flush */ 30 | NULL, /* call */ 31 | NULL, /* event */ 32 | ERL_DRV_EXTENDED_MARKER, /* ERL_DRV_EXTENDED_MARKER */ 33 | ERL_DRV_EXTENDED_MAJOR_VERSION, /* ERL_DRV_EXTENDED_MAJOR_VERSION */ 34 | ERL_DRV_EXTENDED_MAJOR_VERSION, /* ERL_DRV_EXTENDED_MINOR_VERSION */ 35 | ERL_DRV_FLAG_USE_PORT_LOCKING /* ERL_DRV_FLAGs */ 36 | }; 37 | 38 | DRIVER_INIT(lua_driver) { 39 | return &lua_driver_entry; 40 | } 41 | 42 | static ErlDrvData 43 | start(ErlDrvPort port, char *cmd) 44 | { 45 | lua_State *L; 46 | L = luaL_newstate(); 47 | luaL_openlibs(L); 48 | 49 | lua_drv_t* retval = (lua_drv_t*) driver_alloc(sizeof(lua_drv_t)); 50 | retval->port = port; 51 | retval->L = L; 52 | 53 | return (ErlDrvData) retval; 54 | } 55 | 56 | static void 57 | stop(ErlDrvData handle) 58 | { 59 | lua_drv_t* driver_data = (lua_drv_t*) handle; 60 | lua_close(driver_data->L); 61 | driver_free(driver_data); 62 | } 63 | 64 | static void 65 | process(ErlDrvData handle, ErlIOVec *ev) 66 | { 67 | lua_drv_t *driver_data = (lua_drv_t*) handle; 68 | char *buf = ev->binv[1]->orig_bytes; 69 | int index = 0; 70 | int arty, version; 71 | long command; 72 | 73 | ei_decode_version(buf, &index, &version); 74 | ei_decode_tuple_header(buf, &index, &arty); 75 | ei_decode_long(buf, &index, &command); 76 | 77 | // printf("Command: %ld\n", command); 78 | // printf("sizeof: int: %ld, long: %ld, long long: %ld\n", sizeof(int), sizeof(long), sizeof(long long)); 79 | 80 | switch(command) { 81 | case ERL_LUA_CALL: 82 | erl_lua_call(driver_data, buf, index); 83 | break; 84 | case ERL_LUA_CONCAT: 85 | erl_lua_concat(driver_data, buf, index); 86 | break; 87 | case ERL_LUA_GETFIELD: 88 | erl_lua_getfield(driver_data, buf, index); 89 | break; 90 | case ERL_LUA_GETGLOBAL: 91 | erl_lua_getglobal(driver_data, buf, index); 92 | break; 93 | case ERL_LUA_GETTOP: 94 | erl_lua_gettop(driver_data, buf, index); 95 | break; 96 | case ERL_LUA_PUSHBOOLEAN: 97 | erl_lua_pushboolean(driver_data, buf, index); 98 | break; 99 | case ERL_LUA_PUSHINTEGER: 100 | erl_lua_pushinteger(driver_data, buf, index); 101 | break; 102 | case ERL_LUA_PUSHSTRING: 103 | erl_lua_pushstring(driver_data, buf, index); 104 | break; 105 | case ERL_LUA_PUSHNIL: 106 | erl_lua_pushnil(driver_data, buf, index); 107 | break; 108 | case ERL_LUA_PUSHNUMBER: 109 | erl_lua_pushnumber(driver_data, buf, index); 110 | break; 111 | case ERL_LUA_REMOVE: 112 | erl_lua_remove(driver_data, buf, index); 113 | break; 114 | case ERL_LUA_SETFIELD: 115 | erl_lua_setfield(driver_data, buf, index); 116 | break; 117 | case ERL_LUA_SETGLOBAL: 118 | erl_lua_setglobal(driver_data, buf, index); 119 | break; 120 | case ERL_LUA_TOBOOLEAN: 121 | erl_lua_toboolean(driver_data, buf, index); 122 | break; 123 | case ERL_LUA_TOINTEGER: 124 | erl_lua_tointeger(driver_data, buf, index); 125 | break; 126 | case ERL_LUA_TOLSTRING: 127 | erl_lua_tolstring(driver_data, buf, index); 128 | break; 129 | case ERL_LUA_TONUMBER: 130 | erl_lua_tonumber(driver_data, buf, index); 131 | break; 132 | case ERL_LUA_TYPE: 133 | erl_lua_type(driver_data, buf, index); 134 | break; 135 | 136 | case ERL_LUAL_DOSTRING: 137 | erl_lual_dostring(driver_data, buf, index); 138 | break; 139 | 140 | default: 141 | erl_lua_no_command(driver_data); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /c_src/commands.h: -------------------------------------------------------------------------------- 1 | /* General Lua API */ 2 | 3 | #define ERL_LUA_ALLOC 1 4 | #define ERL_LUA_ATPANIC 2 5 | #define ERL_LUA_CALL 3 6 | #define ERL_LUA_CFUNCTION 4 7 | #define ERL_LUA_CHECKSTACK 5 8 | #define ERL_LUA_CLOSE 6 9 | #define ERL_LUA_CONCAT 7 10 | #define ERL_LUA_CPCALL 8 11 | #define ERL_LUA_CREATETABLE 9 12 | #define ERL_LUA_DUMP 10 13 | #define ERL_LUA_EQUAL 11 14 | #define ERL_LUA_ERROR 12 15 | #define ERL_LUA_GC 13 16 | #define ERL_LUA_GETALLOCF 14 17 | #define ERL_LUA_GETFENV 15 18 | #define ERL_LUA_GETFIELD 16 19 | #define ERL_LUA_GETGLOBAL 17 20 | #define ERL_LUA_GETMETATABLE 18 21 | #define ERL_LUA_GETTABLE 19 22 | #define ERL_LUA_GETTOP 20 23 | #define ERL_LUA_INSERT 21 24 | #define ERL_LUA_ISBOOLEAN 22 25 | #define ERL_LUA_ISCFUNCTION 23 26 | #define ERL_LUA_ISFUNCTION 24 27 | #define ERL_LUA_ISLIGHTUSERDATA 25 28 | #define ERL_LUA_ISNIL 26 29 | #define ERL_LUA_ISNONE 27 30 | #define ERL_LUA_ISNONEORNIL 28 31 | #define ERL_LUA_ISNUMBER 29 32 | #define ERL_LUA_ISSTRING 30 33 | #define ERL_LUA_ISTABLE 31 34 | #define ERL_LUA_ISTHREAD 32 35 | #define ERL_LUA_ISUSERDATA 33 36 | #define ERL_LUA_LESSTHAN 34 37 | #define ERL_LUA_LOAD 35 38 | #define ERL_LUA_NEWSTATE 36 39 | #define ERL_LUA_NEWTABLE 37 40 | #define ERL_LUA_NEWTHREAD 38 41 | #define ERL_LUA_NEWUSERDATA 39 42 | #define ERL_LUA_NEXT 40 43 | #define ERL_LUA_OBJLEN 41 44 | #define ERL_LUA_PCALL 42 45 | #define ERL_LUA_POP 43 46 | #define ERL_LUA_PUSHBOOLEAN 44 47 | #define ERL_LUA_PUSHCCLOSURE 45 48 | #define ERL_LUA_PUSHCFUNCTION 46 49 | #define ERL_LUA_PUSHFSTRING 47 50 | #define ERL_LUA_PUSHINTEGER 48 51 | #define ERL_LUA_PUSHLIGHTUSERDATA 49 52 | #define ERL_LUA_PUSHLITERAL 50 53 | #define ERL_LUA_PUSHLSTRING 51 54 | #define ERL_LUA_PUSHNIL 52 55 | #define ERL_LUA_PUSHNUMBER 53 56 | #define ERL_LUA_PUSHSTRING 54 57 | #define ERL_LUA_PUSHTHREAD 55 58 | #define ERL_LUA_PUSHVALUE 56 59 | #define ERL_LUA_PUSHVFSTRING 57 60 | #define ERL_LUA_RAWEQUAL 58 61 | #define ERL_LUA_RAWGET 59 62 | #define ERL_LUA_RAWGETI 60 63 | #define ERL_LUA_RAWSET 61 64 | #define ERL_LUA_RAWSETI 62 65 | #define ERL_LUA_REGISTER 63 66 | #define ERL_LUA_REMOVE 64 67 | #define ERL_LUA_REPLACE 65 68 | #define ERL_LUA_RESUME 66 69 | #define ERL_LUA_SETALLOCF 67 70 | #define ERL_LUA_SETFENV 68 71 | #define ERL_LUA_SETFIELD 69 72 | #define ERL_LUA_SETGLOBAL 70 73 | #define ERL_LUA_SETMETATABLE 71 74 | #define ERL_LUA_SETTABLE 72 75 | #define ERL_LUA_SETTOP 73 76 | #define ERL_LUA_STATUS 74 77 | #define ERL_LUA_TOBOOLEAN 75 78 | #define ERL_LUA_TOCFUNCTION 76 79 | #define ERL_LUA_TOINTEGER 77 80 | #define ERL_LUA_TOLSTRING 78 81 | #define ERL_LUA_TONUMBER 79 82 | #define ERL_LUA_TOPOINTER 80 83 | #define ERL_LUA_TOSTRING 81 84 | #define ERL_LUA_TOTHREAD 82 85 | #define ERL_LUA_TOUSERDATA 83 86 | #define ERL_LUA_TYPE 84 87 | #define ERL_LUA_TYPENAME 85 88 | #define ERL_LUA_XMOVE 86 89 | #define ERL_LUA_YIELD 87 90 | 91 | 92 | /* Lua Auxiliary Library */ 93 | 94 | #define ERL_LUAL_ADDCHAR 88 95 | #define ERL_LUAL_ADDLSTRING 89 96 | #define ERL_LUAL_ADDSIZE 90 97 | #define ERL_LUAL_ADDSTRING 91 98 | #define ERL_LUAL_ADDVALUE 92 99 | #define ERL_LUAL_ARGCHECK 93 100 | #define ERL_LUAL_ARGERROR 94 101 | #define ERL_LUAL_BUFFINIT 95 102 | #define ERL_LUAL_CALLMETA 96 103 | #define ERL_LUAL_CHECKANY 97 104 | #define ERL_LUAL_CHECKINT 98 105 | #define ERL_LUAL_CHECKINTEGER 99 106 | #define ERL_LUAL_CHECKLONG 100 107 | #define ERL_LUAL_CHECKLSTRING 101 108 | #define ERL_LUAL_CHECKNUMBER 102 109 | #define ERL_LUAL_CHECKOPTION 103 110 | #define ERL_LUAL_CHECKSTACK 104 111 | #define ERL_LUAL_CHECKSTRING 105 112 | #define ERL_LUAL_CHECKTYPE 106 113 | #define ERL_LUAL_CHECKUDATA 107 114 | #define ERL_LUAL_DOFILE 108 115 | #define ERL_LUAL_DOSTRING 109 116 | #define ERL_LUAL_ERROR 110 117 | #define ERL_LUAL_GETMETAFIELD 111 118 | #define ERL_LUAL_GETMETATABLE 112 119 | #define ERL_LUAL_GSUB 113 120 | #define ERL_LUAL_LOADBUFFER 114 121 | #define ERL_LUAL_LOADFILE 115 122 | #define ERL_LUAL_LOADSTRING 116 123 | #define ERL_LUAL_NEWMETATABLE 117 124 | #define ERL_LUAL_NEWSTATE 118 125 | #define ERL_LUAL_OPENLIBS 119 126 | #define ERL_LUAL_OPTINT 120 127 | #define ERL_LUAL_OPTINTEGER 121 128 | #define ERL_LUAL_OPTLONG 122 129 | #define ERL_LUAL_OPTLSTRING 123 130 | #define ERL_LUAL_OPTNUMBER 124 131 | #define ERL_LUAL_OPTSTRING 125 132 | #define ERL_LUAL_PREPBUFFER 126 133 | #define ERL_LUAL_PUSHRESULT 127 134 | #define ERL_LUAL_REF 128 135 | #define ERL_LUAL_REGISTER 129 136 | #define ERL_LUAL_TYPENAME 130 137 | #define ERL_LUAL_TYPERROR 131 138 | #define ERL_LUAL_UNREF 132 139 | #define ERL_LUAL_WHERE 133 140 | 141 | #define ATOM_OK driver_mk_atom("ok") 142 | #define ATOM_ERROR driver_mk_atom("error") 143 | -------------------------------------------------------------------------------- /include/lua_api.hrl: -------------------------------------------------------------------------------- 1 | % Lua Type Defs 2 | 3 | -define(LUA_TNIL, 0 ). 4 | -define(LUA_TBOOLEAN, 1 ). 5 | -define(LUA_TLIGHTUSERDATA, 2 ). 6 | -define(LUA_TNUMBER, 3 ). 7 | -define(LUA_TSTRING, 4 ). 8 | -define(LUA_TTABLE, 5 ). 9 | -define(LUA_TFUNCTION, 6 ). 10 | -define(LUA_TUSERDATA, 7 ). 11 | -define(LUA_TTHREAD, 8 ). 12 | 13 | % General Lua API 14 | 15 | -define(ERL_LUA_ALLOC, 1 ). 16 | -define(ERL_LUA_ATPANIC, 2 ). 17 | -define(ERL_LUA_CALL, 3 ). 18 | -define(ERL_LUA_CFUNCTION, 4 ). 19 | -define(ERL_LUA_CHECKSTACK, 5 ). 20 | -define(ERL_LUA_CLOSE, 6 ). 21 | -define(ERL_LUA_CONCAT, 7 ). 22 | -define(ERL_LUA_CPCALL, 8 ). 23 | -define(ERL_LUA_CREATETABLE, 9 ). 24 | -define(ERL_LUA_DUMP, 10). 25 | -define(ERL_LUA_EQUAL, 11). 26 | -define(ERL_LUA_ERROR, 12). 27 | -define(ERL_LUA_GC, 13). 28 | -define(ERL_LUA_GETALLOCF, 14). 29 | -define(ERL_LUA_GETFENV, 15). 30 | -define(ERL_LUA_GETFIELD, 16). 31 | -define(ERL_LUA_GETGLOBAL, 17). 32 | -define(ERL_LUA_GETMETATABLE, 18). 33 | -define(ERL_LUA_GETTABLE, 19). 34 | -define(ERL_LUA_GETTOP, 20). 35 | -define(ERL_LUA_INSERT, 21). 36 | -define(ERL_LUA_ISBOOLEAN, 22). 37 | -define(ERL_LUA_ISCFUNCTION, 23). 38 | -define(ERL_LUA_ISFUNCTION, 24). 39 | -define(ERL_LUA_ISLIGHTUSERDATA, 25). 40 | -define(ERL_LUA_ISNIL, 26). 41 | -define(ERL_LUA_ISNONE, 27). 42 | -define(ERL_LUA_ISNONEORNIL, 28). 43 | -define(ERL_LUA_ISNUMBER, 29). 44 | -define(ERL_LUA_ISSTRING, 30). 45 | -define(ERL_LUA_ISTABLE, 31). 46 | -define(ERL_LUA_ISTHREAD, 32). 47 | -define(ERL_LUA_ISUSERDATA, 33). 48 | -define(ERL_LUA_LESSTHAN, 34). 49 | -define(ERL_LUA_LOAD, 35). 50 | -define(ERL_LUA_NEWSTATE, 36). 51 | -define(ERL_LUA_NEWTABLE, 37). 52 | -define(ERL_LUA_NEWTHREAD, 38). 53 | -define(ERL_LUA_NEWUSERDATA, 39). 54 | -define(ERL_LUA_NEXT, 40). 55 | -define(ERL_LUA_OBJLEN, 41). 56 | -define(ERL_LUA_PCALL, 42). 57 | -define(ERL_LUA_POP, 43). 58 | -define(ERL_LUA_PUSHBOOLEAN, 44). 59 | -define(ERL_LUA_PUSHCCLOSURE, 45). 60 | -define(ERL_LUA_PUSHCFUNCTION, 46). 61 | -define(ERL_LUA_PUSHFSTRING, 47). 62 | -define(ERL_LUA_PUSHINTEGER, 48). 63 | -define(ERL_LUA_PUSHLIGHTUSERDATA, 49). 64 | -define(ERL_LUA_PUSHLITERAL, 50). 65 | -define(ERL_LUA_PUSHLSTRING, 51). 66 | -define(ERL_LUA_PUSHNIL, 52). 67 | -define(ERL_LUA_PUSHNUMBER, 53). 68 | -define(ERL_LUA_PUSHSTRING, 54). 69 | -define(ERL_LUA_PUSHTHREAD, 55). 70 | -define(ERL_LUA_PUSHVALUE, 56). 71 | -define(ERL_LUA_PUSHVFSTRING, 57). 72 | -define(ERL_LUA_RAWEQUAL, 58). 73 | -define(ERL_LUA_RAWGET, 59). 74 | -define(ERL_LUA_RAWGETI, 60). 75 | -define(ERL_LUA_RAWSET, 61). 76 | -define(ERL_LUA_RAWSETI, 62). 77 | -define(ERL_LUA_REGISTER, 63). 78 | -define(ERL_LUA_REMOVE, 64). 79 | -define(ERL_LUA_REPLACE, 65). 80 | -define(ERL_LUA_RESUME, 66). 81 | -define(ERL_LUA_SETALLOCF, 67). 82 | -define(ERL_LUA_SETFENV, 68). 83 | -define(ERL_LUA_SETFIELD, 69). 84 | -define(ERL_LUA_SETGLOBAL, 70). 85 | -define(ERL_LUA_SETMETATABLE, 71). 86 | -define(ERL_LUA_SETTABLE, 72). 87 | -define(ERL_LUA_SETTOP, 73). 88 | -define(ERL_LUA_STATUS, 74). 89 | -define(ERL_LUA_TOBOOLEAN, 75). 90 | -define(ERL_LUA_TOCFUNCTION, 76). 91 | -define(ERL_LUA_TOINTEGER, 77). 92 | -define(ERL_LUA_TOLSTRING, 78). 93 | -define(ERL_LUA_TONUMBER, 79). 94 | -define(ERL_LUA_TOPOINTER, 80). 95 | -define(ERL_LUA_TOSTRING, 81). 96 | -define(ERL_LUA_TOTHREAD, 82). 97 | -define(ERL_LUA_TOUSERDATA, 83). 98 | -define(ERL_LUA_TYPE, 84). 99 | -define(ERL_LUA_TYPENAME, 85). 100 | -define(ERL_LUA_XMOVE, 86). 101 | -define(ERL_LUA_YIELD, 87). 102 | 103 | 104 | %% Lua Auxiliary Library 105 | 106 | -define(ERL_LUAL_ADDCHAR, 88 ). 107 | -define(ERL_LUAL_ADDLSTRING, 89 ). 108 | -define(ERL_LUAL_ADDSIZE, 90 ). 109 | -define(ERL_LUAL_ADDSTRING, 91 ). 110 | -define(ERL_LUAL_ADDVALUE, 92 ). 111 | -define(ERL_LUAL_ARGCHECK, 93 ). 112 | -define(ERL_LUAL_ARGERROR, 94 ). 113 | -define(ERL_LUAL_BUFFINIT, 95 ). 114 | -define(ERL_LUAL_CALLMETA, 96 ). 115 | -define(ERL_LUAL_CHECKANY, 97 ). 116 | -define(ERL_LUAL_CHECKINT, 98 ). 117 | -define(ERL_LUAL_CHECKINTEGER, 99 ). 118 | -define(ERL_LUAL_CHECKLONG, 100). 119 | -define(ERL_LUAL_CHECKLSTRING, 101). 120 | -define(ERL_LUAL_CHECKNUMBER, 102). 121 | -define(ERL_LUAL_CHECKOPTION, 103). 122 | -define(ERL_LUAL_CHECKSTACK, 104). 123 | -define(ERL_LUAL_CHECKSTRING, 105). 124 | -define(ERL_LUAL_CHECKTYPE, 106). 125 | -define(ERL_LUAL_CHECKUDATA, 107). 126 | -define(ERL_LUAL_DOFILE, 108). 127 | -define(ERL_LUAL_DOSTRING, 109). 128 | -define(ERL_LUAL_ERROR, 110). 129 | -define(ERL_LUAL_GETMETAFIELD, 111). 130 | -define(ERL_LUAL_GETMETATABLE, 112). 131 | -define(ERL_LUAL_GSUB, 113). 132 | -define(ERL_LUAL_LOADBUFFER, 114). 133 | -define(ERL_LUAL_LOADFILE, 115). 134 | -define(ERL_LUAL_LOADSTRING, 116). 135 | -define(ERL_LUAL_NEWMETATABLE, 117). 136 | -define(ERL_LUAL_NEWSTATE, 118). 137 | -define(ERL_LUAL_OPENLIBS, 119). 138 | -define(ERL_LUAL_OPTINT, 120). 139 | -define(ERL_LUAL_OPTINTEGER, 121). 140 | -define(ERL_LUAL_OPTLONG, 122). 141 | -define(ERL_LUAL_OPTLSTRING, 123). 142 | -define(ERL_LUAL_OPTNUMBER, 124). 143 | -define(ERL_LUAL_OPTSTRING, 125). 144 | -define(ERL_LUAL_PREPBUFFER, 126). 145 | -define(ERL_LUAL_PUSHRESULT, 127). 146 | -define(ERL_LUAL_REF, 128). 147 | -define(ERL_LUAL_REGISTER, 129). 148 | -define(ERL_LUAL_TYPENAME, 130). 149 | -define(ERL_LUAL_TYPERROR, 131). 150 | -define(ERL_LUAL_UNREF, 132). 151 | -define(ERL_LUAL_WHERE, 133). -------------------------------------------------------------------------------- /c_src/commands.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "lua_drv.h" 8 | #include "commands.h" 9 | 10 | static void reply_ok(lua_drv_t *driver_data); 11 | static void reply_error(lua_drv_t *driver_data); 12 | static char* decode_string(char *buf, int *index); 13 | 14 | 15 | void 16 | erl_lua_call(lua_drv_t *driver_data, char *buf, int index) 17 | { 18 | long args, results; 19 | 20 | ei_decode_long(buf, &index, &args); 21 | ei_decode_long(buf, &index, &results); 22 | 23 | lua_call(driver_data->L, args, results); 24 | 25 | reply_ok(driver_data); 26 | } 27 | 28 | void 29 | erl_lua_concat(lua_drv_t *driver_data, char *buf, int index) 30 | { 31 | long n; 32 | 33 | ei_decode_long(buf, &index, &n); 34 | 35 | lua_concat(driver_data->L, n); 36 | 37 | reply_ok(driver_data); 38 | } 39 | 40 | void 41 | erl_lua_getfield(lua_drv_t *driver_data, char *buf, int index) 42 | { 43 | long i; 44 | char *name; 45 | 46 | ei_decode_long(buf, &index, &i); 47 | name = decode_string(buf, &index); 48 | 49 | lua_getfield(driver_data->L, i, name); 50 | 51 | reply_ok(driver_data); 52 | free(name); 53 | } 54 | 55 | void 56 | erl_lua_getglobal(lua_drv_t *driver_data, char *buf, int index) 57 | { 58 | char *name; 59 | 60 | name = decode_string(buf, &index); 61 | 62 | lua_getglobal(driver_data->L, name); 63 | 64 | reply_ok(driver_data); 65 | free(name); 66 | } 67 | 68 | void 69 | erl_lua_gettop(lua_drv_t *driver_data, char *buf, int index) 70 | { 71 | int size; 72 | 73 | size = lua_gettop(driver_data->L); 74 | 75 | ErlDrvTermData spec[] = { 76 | ERL_DRV_ATOM, ATOM_OK, 77 | ERL_DRV_INT, (ErlDrvTermData) size, 78 | ERL_DRV_TUPLE, 2 79 | }; 80 | driver_output_term(driver_data->port, spec, sizeof(spec) / sizeof(spec[0])); 81 | } 82 | 83 | void 84 | erl_lua_pushboolean(lua_drv_t *driver_data, char *buf, int index) 85 | { 86 | int b; 87 | 88 | ei_decode_boolean(buf, &index, &b); 89 | 90 | lua_pushboolean(driver_data->L, b); 91 | 92 | reply_ok(driver_data); 93 | } 94 | 95 | void 96 | erl_lua_pushinteger(lua_drv_t *driver_data, char *buf, int index) 97 | { 98 | long long num; 99 | 100 | ei_decode_longlong(buf, &index, &num); 101 | 102 | lua_pushinteger(driver_data->L, num); 103 | 104 | reply_ok(driver_data); 105 | } 106 | 107 | void 108 | erl_lua_pushstring(lua_drv_t *driver_data, char *buf, int index) 109 | { 110 | char *str; 111 | 112 | str = decode_string(buf, &index); 113 | 114 | lua_pushstring(driver_data->L, str); 115 | 116 | reply_ok(driver_data); 117 | free(str); 118 | } 119 | 120 | void 121 | erl_lua_pushnil(lua_drv_t *driver_data, char *buf, int index) 122 | { 123 | lua_pushnil(driver_data->L); 124 | reply_ok(driver_data); 125 | } 126 | 127 | void 128 | erl_lua_pushnumber(lua_drv_t *driver_data, char *buf, int index) 129 | { 130 | double dnum; 131 | long long lnum; 132 | int type, len; 133 | 134 | ei_get_type(buf, &index, &type, &len); 135 | 136 | switch (type) { 137 | case ERL_FLOAT_EXT: 138 | ei_decode_double(buf, &index, &dnum); 139 | lua_pushnumber(driver_data->L, dnum); 140 | break; 141 | default: 142 | ei_decode_longlong(buf, &index, &lnum); 143 | lua_pushnumber(driver_data->L, lnum); 144 | break; 145 | } 146 | 147 | reply_ok(driver_data); 148 | } 149 | 150 | void 151 | erl_lua_remove(lua_drv_t *driver_data, char *buf, int index) 152 | { 153 | long i; 154 | 155 | ei_decode_long(buf, &index, &i); 156 | 157 | lua_remove(driver_data->L, i); 158 | 159 | reply_ok(driver_data); 160 | } 161 | 162 | void 163 | erl_lua_setfield(lua_drv_t *driver_data, char *buf, int index) 164 | { 165 | long i; 166 | char *name; 167 | 168 | ei_decode_long(buf, &index, &i); 169 | name = decode_string(buf, &index); 170 | 171 | lua_setfield(driver_data->L, i, name); 172 | 173 | reply_ok(driver_data); 174 | free(name); 175 | } 176 | 177 | void 178 | erl_lua_setglobal(lua_drv_t *driver_data, char *buf, int index) 179 | { 180 | char *name; 181 | 182 | name = decode_string(buf, &index); 183 | 184 | lua_setglobal(driver_data->L, name); 185 | 186 | reply_ok(driver_data); 187 | free(name); 188 | } 189 | 190 | void 191 | erl_lua_toboolean(lua_drv_t *driver_data, char *buf, int index) 192 | { 193 | long i; 194 | int res; 195 | ErlDrvTermData spec[2]; 196 | spec[0] = ERL_DRV_ATOM; 197 | 198 | ei_decode_long(buf, &index, &i); 199 | 200 | res = lua_toboolean(driver_data->L, i); 201 | if (res) 202 | spec[1] = driver_mk_atom("true"); 203 | else 204 | spec[1] = driver_mk_atom("false"); 205 | driver_output_term(driver_data->port, spec, sizeof(spec) / sizeof(spec[0])); 206 | } 207 | 208 | void 209 | erl_lua_tointeger(lua_drv_t *driver_data, char *buf, int index) 210 | { 211 | long i; 212 | long long res; 213 | 214 | ei_decode_long(buf, &index, &i); 215 | 216 | res = lua_tointeger(driver_data->L, i); 217 | 218 | ErlDrvTermData spec[] = { 219 | ERL_DRV_ATOM, ATOM_OK, 220 | ERL_DRV_INT, (ErlDrvTermData) res, 221 | ERL_DRV_TUPLE, 2 222 | }; 223 | driver_output_term(driver_data->port, spec, sizeof(spec) / sizeof(spec[0])); 224 | } 225 | 226 | void 227 | erl_lua_tolstring(lua_drv_t *driver_data, char *buf, int index) 228 | { 229 | size_t len; 230 | long i; 231 | const char *str; 232 | 233 | ei_decode_long(buf, &index, &i); 234 | 235 | str = lua_tolstring(driver_data->L, i, &len); 236 | 237 | ErlDrvTermData spec[] = { 238 | ERL_DRV_ATOM, ATOM_OK, 239 | ERL_DRV_STRING, (ErlDrvTermData) str, len, 240 | ERL_DRV_TUPLE, 2 241 | }; 242 | driver_output_term(driver_data->port, spec, sizeof(spec) / sizeof(spec[0])); 243 | } 244 | 245 | 246 | /* TODO: return a binary instead of a list that is then converted to a binary */ 247 | void 248 | erl_lua_tonumber(lua_drv_t *driver_data, char *buf, int index) 249 | { 250 | long i; 251 | double res; 252 | int encode_i = 0; 253 | int size; 254 | char *eibuf; 255 | 256 | ei_decode_long(buf, &index, &i); 257 | 258 | res = lua_tonumber(driver_data->L, i); 259 | 260 | ei_encode_version(NULL, &encode_i); 261 | if ((long long) res == res) { 262 | ei_encode_longlong(NULL, &encode_i, (long long) res); 263 | size = encode_i; 264 | encode_i = 0; 265 | eibuf = malloc(sizeof(char) * (size + 1)); 266 | 267 | ei_encode_version(eibuf, &encode_i); 268 | ei_encode_longlong(eibuf, &encode_i, res); 269 | } else { 270 | ei_encode_double(NULL, &encode_i, res); 271 | size = encode_i; 272 | encode_i = 0; 273 | eibuf = malloc(sizeof(char) * (size + 1)); 274 | 275 | ei_encode_version(eibuf, &encode_i); 276 | ei_encode_double(eibuf, &encode_i, res); 277 | } 278 | 279 | ErlDrvTermData spec[] = { 280 | ERL_DRV_ATOM, ATOM_OK, 281 | ERL_DRV_STRING, (ErlDrvTermData) eibuf, size, 282 | ERL_DRV_TUPLE, 2 283 | }; 284 | driver_output_term(driver_data->port, spec, sizeof(spec) / sizeof(spec[0])); 285 | free(eibuf); 286 | //driver_free_binary(bin); 287 | } 288 | 289 | void 290 | erl_lua_type(lua_drv_t *driver_data, char *buf, int index) 291 | { 292 | long i; 293 | int lua_t; 294 | 295 | ei_decode_long(buf, &index, &i); 296 | 297 | lua_t = lua_type(driver_data->L, i); 298 | 299 | ErlDrvTermData spec[] = { 300 | ERL_DRV_ATOM, ATOM_OK, 301 | ERL_DRV_INT, (ErlDrvTermData) lua_t, 302 | ERL_DRV_TUPLE, 2 303 | }; 304 | driver_output_term(driver_data->port, spec, sizeof(spec) / sizeof(spec[0])); 305 | } 306 | 307 | 308 | void 309 | erl_lual_dostring(lua_drv_t *driver_data, char *buf, int index) 310 | { 311 | char *code; 312 | 313 | code = decode_string(buf, &index); 314 | 315 | if (!luaL_dostring(driver_data->L, code)) 316 | reply_ok(driver_data); 317 | else 318 | reply_error(driver_data); 319 | } 320 | 321 | 322 | void 323 | erl_lua_no_command(lua_drv_t *driver_data) 324 | { 325 | ErlDrvTermData spec[] = { 326 | ERL_DRV_ATOM, ATOM_ERROR, 327 | ERL_DRV_STRING, (ErlDrvTermData) "No Command Found", 16, 328 | ERL_DRV_TUPLE, 2 329 | }; 330 | driver_output_term(driver_data->port, spec, sizeof(spec) / sizeof(spec[0])); 331 | } 332 | 333 | 334 | static void 335 | reply_ok(lua_drv_t *driver_data) 336 | { 337 | ErlDrvTermData spec[] = {ERL_DRV_ATOM, ATOM_OK}; 338 | driver_output_term(driver_data->port, spec, sizeof(spec) / sizeof(spec[0])); 339 | } 340 | 341 | static void 342 | reply_error(lua_drv_t *driver_data) 343 | { 344 | ErlDrvTermData spec[] = {ERL_DRV_ATOM, ATOM_ERROR}; 345 | driver_output_term(driver_data->port, spec, sizeof(spec) / sizeof(spec[0])); 346 | } 347 | 348 | 349 | static char* 350 | decode_string(char *buf, int *index) 351 | { 352 | int type, length; 353 | char *str; 354 | 355 | ei_get_type(buf, index, &type, &length); 356 | str = malloc(sizeof(char) * (length + 1)); 357 | ei_decode_string(buf, index, str); 358 | return str; 359 | } 360 | --------------------------------------------------------------------------------