rlua 1.0rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. data/LICENSE.rdoc +167 -0
  2. data/README.rdoc +97 -0
  3. data/ext/extconf.rb +10 -0
  4. data/ext/rlua.c +1239 -0
  5. data/lib/rlua.rb +82 -0
  6. metadata +63 -0
data/LICENSE.rdoc ADDED
@@ -0,0 +1,167 @@
1
+ .
2
+ GNU LESSER GENERAL PUBLIC LICENSE
3
+ Version 3, 29 June 2007
4
+
5
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
6
+ Everyone is permitted to copy and distribute verbatim copies
7
+ of this license document, but changing it is not allowed.
8
+
9
+
10
+ This version of the GNU Lesser General Public License incorporates
11
+ the terms and conditions of version 3 of the GNU General Public
12
+ License, supplemented by the additional permissions listed below.
13
+
14
+ 0. Additional Definitions.
15
+
16
+ As used herein, "this License" refers to version 3 of the GNU Lesser
17
+ General Public License, and the "GNU GPL" refers to version 3 of the GNU
18
+ General Public License.
19
+
20
+ "The Library" refers to a covered work governed by this License,
21
+ other than an Application or a Combined Work as defined below.
22
+
23
+ An "Application" is any work that makes use of an interface provided
24
+ by the Library, but which is not otherwise based on the Library.
25
+ Defining a subclass of a class defined by the Library is deemed a mode
26
+ of using an interface provided by the Library.
27
+
28
+ A "Combined Work" is a work produced by combining or linking an
29
+ Application with the Library. The particular version of the Library
30
+ with which the Combined Work was made is also called the "Linked
31
+ Version".
32
+
33
+ The "Minimal Corresponding Source" for a Combined Work means the
34
+ Corresponding Source for the Combined Work, excluding any source code
35
+ for portions of the Combined Work that, considered in isolation, are
36
+ based on the Application, and not on the Linked Version.
37
+
38
+ The "Corresponding Application Code" for a Combined Work means the
39
+ object code and/or source code for the Application, including any data
40
+ and utility programs needed for reproducing the Combined Work from the
41
+ Application, but excluding the System Libraries of the Combined Work.
42
+
43
+ 1. Exception to Section 3 of the GNU GPL.
44
+
45
+ You may convey a covered work under sections 3 and 4 of this License
46
+ without being bound by section 3 of the GNU GPL.
47
+
48
+ 2. Conveying Modified Versions.
49
+
50
+ If you modify a copy of the Library, and, in your modifications, a
51
+ facility refers to a function or data to be supplied by an Application
52
+ that uses the facility (other than as an argument passed when the
53
+ facility is invoked), then you may convey a copy of the modified
54
+ version:
55
+
56
+ a) under this License, provided that you make a good faith effort to
57
+ ensure that, in the event an Application does not supply the
58
+ function or data, the facility still operates, and performs
59
+ whatever part of its purpose remains meaningful, or
60
+
61
+ b) under the GNU GPL, with none of the additional permissions of
62
+ this License applicable to that copy.
63
+
64
+ 3. Object Code Incorporating Material from Library Header Files.
65
+
66
+ The object code form of an Application may incorporate material from
67
+ a header file that is part of the Library. You may convey such object
68
+ code under terms of your choice, provided that, if the incorporated
69
+ material is not limited to numerical parameters, data structure
70
+ layouts and accessors, or small macros, inline functions and templates
71
+ (ten or fewer lines in length), you do both of the following:
72
+
73
+ a) Give prominent notice with each copy of the object code that the
74
+ Library is used in it and that the Library and its use are
75
+ covered by this License.
76
+
77
+ b) Accompany the object code with a copy of the GNU GPL and this license
78
+ document.
79
+
80
+ 4. Combined Works.
81
+
82
+ You may convey a Combined Work under terms of your choice that,
83
+ taken together, effectively do not restrict modification of the
84
+ portions of the Library contained in the Combined Work and reverse
85
+ engineering for debugging such modifications, if you also do each of
86
+ the following:
87
+
88
+ a) Give prominent notice with each copy of the Combined Work that
89
+ the Library is used in it and that the Library and its use are
90
+ covered by this License.
91
+
92
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
93
+ document.
94
+
95
+ c) For a Combined Work that displays copyright notices during
96
+ execution, include the copyright notice for the Library among
97
+ these notices, as well as a reference directing the user to the
98
+ copies of the GNU GPL and this license document.
99
+
100
+ d) Do one of the following:
101
+
102
+ 0) Convey the Minimal Corresponding Source under the terms of this
103
+ License, and the Corresponding Application Code in a form
104
+ suitable for, and under terms that permit, the user to
105
+ recombine or relink the Application with a modified version of
106
+ the Linked Version to produce a modified Combined Work, in the
107
+ manner specified by section 6 of the GNU GPL for conveying
108
+ Corresponding Source.
109
+
110
+ 1) Use a suitable shared library mechanism for linking with the
111
+ Library. A suitable mechanism is one that (a) uses at run time
112
+ a copy of the Library already present on the user's computer
113
+ system, and (b) will operate properly with a modified version
114
+ of the Library that is interface-compatible with the Linked
115
+ Version.
116
+
117
+ e) Provide Installation Information, but only if you would otherwise
118
+ be required to provide such information under section 6 of the
119
+ GNU GPL, and only to the extent that such information is
120
+ necessary to install and execute a modified version of the
121
+ Combined Work produced by recombining or relinking the
122
+ Application with a modified version of the Linked Version. (If
123
+ you use option 4d0, the Installation Information must accompany
124
+ the Minimal Corresponding Source and Corresponding Application
125
+ Code. If you use option 4d1, you must provide the Installation
126
+ Information in the manner specified by section 6 of the GNU GPL
127
+ for conveying Corresponding Source.)
128
+
129
+ 5. Combined Libraries.
130
+
131
+ You may place library facilities that are a work based on the
132
+ Library side by side in a single library together with other library
133
+ facilities that are not Applications and are not covered by this
134
+ License, and convey such a combined library under terms of your
135
+ choice, if you do both of the following:
136
+
137
+ a) Accompany the combined library with a copy of the same work based
138
+ on the Library, uncombined with any other library facilities,
139
+ conveyed under the terms of this License.
140
+
141
+ b) Give prominent notice with the combined library that part of it
142
+ is a work based on the Library, and explaining where to find the
143
+ accompanying uncombined form of the same work.
144
+
145
+ 6. Revised Versions of the GNU Lesser General Public License.
146
+
147
+ The Free Software Foundation may publish revised and/or new versions
148
+ of the GNU Lesser General Public License from time to time. Such new
149
+ versions will be similar in spirit to the present version, but may
150
+ differ in detail to address new problems or concerns.
151
+
152
+ Each version is given a distinguishing version number. If the
153
+ Library as you received it specifies that a certain numbered version
154
+ of the GNU Lesser General Public License "or any later version"
155
+ applies to it, you have the option of following the terms and
156
+ conditions either of that published version or of any later version
157
+ published by the Free Software Foundation. If the Library as you
158
+ received it does not specify a version number of the GNU Lesser
159
+ General Public License, you may choose any version of the GNU Lesser
160
+ General Public License ever published by the Free Software Foundation.
161
+
162
+ If the Library as you received it specifies that a proxy can decide
163
+ whether future versions of the GNU Lesser General Public License shall
164
+ apply, that proxy's public statement of acceptance of any version is
165
+ permanent authorization for you to choose that version for the
166
+ Library.
167
+
data/README.rdoc ADDED
@@ -0,0 +1,97 @@
1
+ = Description
2
+ RLua is Ruby to Lua bindings library that features almost full coverage of Lua
3
+ C API, seamless translation of Lua and Ruby objects into each other, calling Lua
4
+ functions from Ruby and vice versa.
5
+
6
+ RLua currently uses Lua 5.1, and is Ruby 1.8, 1.9 and 1.9.1 compatible.
7
+
8
+ = Installation
9
+ RLua is distributed as gem package through rubygems.org, so the procedure is
10
+ quite usual. It uses native Lua C API, so it will need to compile an extension
11
+ during installation.
12
+
13
+ On Linux, you will need to install Lua development files first.
14
+ They are packaged as <tt>liblua5.1-dev</tt> in Debian and it's derivatives
15
+ (like Ubuntu).
16
+
17
+ On Windows, you will need MSVC to compile everything. Through I did not tested
18
+ this (and so cannot provide a detailed description), it should work fine.
19
+
20
+ = Example code
21
+
22
+ require 'rlua'
23
+
24
+ state = Lua::State.new # create Lua interpreter
25
+ state.__load_stdlib :all # load some standard libraries in it
26
+ state.__eval "print('hello, world')" # launch some Lua code
27
+
28
+ state.value = 10 # set a variable in Ruby
29
+ state.__eval "print(value)" # show it's value from Lua
30
+
31
+ state.__eval "value = 15" # set a variable in Lua
32
+ p state.value # show it's value from Ruby
33
+
34
+ # create a function in Lua
35
+ state.__eval "function lua_func() print('hello from Lua') end"
36
+ # launch it from Ruby
37
+ state.lua_func
38
+
39
+ # create a table in Ruby and method in it
40
+ state.ruby = {
41
+ 'meaning_of_life' => 42,
42
+ 'zaphod' => lambda { |this|
43
+ p "Meaning of life: #{this.meaning_of_life}"
44
+ }
45
+ }
46
+ # launch that from Lua as instance method
47
+ state.__eval "ruby:zaphod()"
48
+
49
+ = Type conversion
50
+ Lua and Ruby types are seamlessly translated into each other when calling functions,
51
+ changing tables and so on. The translation is conservative: you can convert a
52
+ value from Ruby to Lua, then backwards and will always receive an object that
53
+ will behave absolutely the same.
54
+
55
+ Here is a table of type mapping:
56
+ <b>Ruby type</b>:: <b>Lua type</b>
57
+ nil:: nil
58
+ Boolean (TrueClass or FalseClass):: true or false
59
+ Fixnum, Bignum or Float:: number
60
+ Proc:: function
61
+ String:: string
62
+ Hash:: table
63
+ Array:: table (with numeric keys)
64
+
65
+ Hashes and Arrays are translated recursively: all keys and values are translated too.
66
+ Getting any Lua function to Ruby code (even the Ruby proc that was translated
67
+ before) results in Lua::Function created, and tables behave the same creating
68
+ Lua::Table object.
69
+
70
+ Proc objects are duck-typed: anything that responds to +call+ method is considered
71
+ Proc.
72
+
73
+ Translation of any object not in the list is impossible and will generate an
74
+ TypeError exception.
75
+
76
+ = Notes
77
+ Most functions are named much like their C API counterparts.
78
+
79
+ 'Ruby-object-like' table indexing convention is described in Lua::Table,
80
+ and function calling is described in Lua::Function.
81
+
82
+ = Author
83
+ RLua is currently developed solely by Peter Zotov &lt;whitequark@whitequark.ru&gt;.
84
+
85
+ = License
86
+ This program is free software: you can redistribute it and/or modify
87
+ it under the terms of the GNU Lesser General Public License as published by
88
+ the Free Software Foundation, either version 3 of the License, or
89
+ (at your option) any later version.
90
+
91
+ This program is distributed in the hope that it will be useful,
92
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
93
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
94
+ GNU Lesser General Public License for more details.
95
+
96
+ You should have received a copy of the GNU Lesser General Public License
97
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
data/ext/extconf.rb ADDED
@@ -0,0 +1,10 @@
1
+ require "mkmf"
2
+
3
+ dir_config('lua5.1')
4
+
5
+ unless have_library('lua5.1', 'luaL_newstate')
6
+ puts ' extconf failure: need liblua5.1'
7
+ exit 1
8
+ end
9
+
10
+ create_makefile("rlua")
data/ext/rlua.c ADDED
@@ -0,0 +1,1239 @@
1
+ /*
2
+ * This file is part of RLua.
3
+ *
4
+ * RLua is free software: you can redistribute it and/or modify
5
+ * it under the terms of the GNU Lesser General Public License as
6
+ * published by the Free Software Foundation, either version 3 of
7
+ * the License, or (at your option) any later version.
8
+ *
9
+ * RLua is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ * GNU Lesser General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU Lesser General Public
15
+ * License along with RLua. If not, see <http://www.gnu.org/licenses/>.
16
+ */
17
+
18
+ #include <ruby.h>
19
+ #include <lua5.1/lua.h>
20
+ #include <lua5.1/lauxlib.h>
21
+ #include <lua5.1/lualib.h>
22
+ #include <ctype.h>
23
+
24
+ VALUE mLua, cLuaState, cLuaMultret, cLuaFunction, cLuaTable;
25
+
26
+ static VALUE rlua_makeref(lua_State* state)
27
+ {
28
+ VALUE ref;
29
+ // stack: |objt|...
30
+ lua_getfield(state, LUA_REGISTRYINDEX, "rlua"); // |refs|objt|...
31
+ lua_pushvalue(state, -2); // |objt|refs|objt|...
32
+ ref = INT2FIX(luaL_ref(state, -2)); // |refs|objt|...
33
+ lua_pop(state, 1); // |objt|...
34
+
35
+ return ref;
36
+ }
37
+
38
+ static VALUE rlua_finalize_ref(VALUE id, VALUE rbState)
39
+ {
40
+ lua_State* state;
41
+ Data_Get_Struct(rbState, lua_State, state);
42
+
43
+ int ref = FIX2INT(rb_hash_aref(rb_iv_get(rbState, "@refs"), id));
44
+
45
+ lua_getfield(state, LUA_REGISTRYINDEX, "rlua");
46
+ luaL_unref(state, -1, ref);
47
+ lua_pop(state, 1);
48
+
49
+ rb_hash_delete(rb_iv_get(rbState, "@refs"), id);
50
+
51
+ return Qnil;
52
+ }
53
+
54
+ static void rlua_add_ref_finalizer(VALUE state, VALUE ref, VALUE object)
55
+ {
56
+ rb_hash_aset(rb_iv_get(state, "@refs"), rb_obj_id(object), ref);
57
+
58
+ VALUE mObjectSpace = rb_const_get(rb_cObject, rb_intern("ObjectSpace"));
59
+ VALUE proc = rb_proc_new(rlua_finalize_ref, state);
60
+ rb_funcall(mObjectSpace, rb_intern("define_finalizer"), 2, object, proc);
61
+ }
62
+
63
+ static VALUE rlua_get_var(lua_State *state)
64
+ {
65
+ VALUE rbLuaState;
66
+ lua_getfield(state, LUA_REGISTRYINDEX, "rlua_state");
67
+ rbLuaState = (VALUE) lua_touserdata(state, -1);
68
+ lua_pop(state, 1);
69
+
70
+ switch(lua_type(state, -1)) {
71
+ case LUA_TNONE:
72
+ case LUA_TNIL:
73
+ return Qnil;
74
+
75
+ case LUA_TTHREAD:
76
+ rb_warn("cannot pop LUA_TTHREAD");
77
+ return Qnil;
78
+
79
+ case LUA_TUSERDATA:
80
+ rb_warn("cannot pop LUA_TUSERDATA");
81
+ return Qnil;
82
+
83
+ case LUA_TLIGHTUSERDATA:
84
+ rb_warn("cannot pop LUA_TLIGHTUSERDATA");
85
+ return Qnil;
86
+
87
+ case LUA_TBOOLEAN:
88
+ return lua_toboolean(state, -1) ? Qtrue : Qfalse;
89
+
90
+ case LUA_TNUMBER:
91
+ return rb_float_new(lua_tonumber(state, -1));
92
+
93
+ case LUA_TSTRING: {
94
+ size_t length;
95
+ const char* string;
96
+ string = lua_tolstring(state, -1, &length);
97
+ return rb_str_new(string, length);
98
+ }
99
+
100
+ case LUA_TTABLE:
101
+ return rb_funcall(cLuaTable, rb_intern("new"), 2, rbLuaState, rlua_makeref(state));
102
+
103
+ case LUA_TFUNCTION:
104
+ return rb_funcall(cLuaFunction, rb_intern("new"), 2, rbLuaState, rlua_makeref(state));
105
+
106
+ default:
107
+ rb_bug("rlua_get_var: unknown type %s", lua_typename(state, lua_type(state, -1)));
108
+ }
109
+ }
110
+
111
+ static void rlua_push_var(lua_State *state, VALUE value)
112
+ {
113
+ switch (TYPE(value)) {
114
+ case T_NIL:
115
+ lua_pushnil(state);
116
+ break;
117
+
118
+ case T_STRING:
119
+ lua_pushlstring(state, RSTRING_PTR(value), RSTRING_LEN(value));
120
+ break;
121
+
122
+ case T_FIXNUM:
123
+ lua_pushnumber(state, FIX2INT(value));
124
+ break;
125
+
126
+ case T_BIGNUM:
127
+ case T_FLOAT:
128
+ lua_pushnumber(state, NUM2DBL(value));
129
+ break;
130
+
131
+ case T_ARRAY: {
132
+ int table, i;
133
+
134
+ lua_newtable(state);
135
+ table = lua_gettop(state);
136
+ for(i = 0; i < RARRAY_LEN(value); i++) {
137
+ rlua_push_var(state, RARRAY_PTR(value)[i]);
138
+ lua_rawseti(state, table, i+1);
139
+ }
140
+ break;
141
+ }
142
+
143
+ case T_HASH: {
144
+ int i;
145
+ VALUE keys;
146
+
147
+ lua_newtable(state);
148
+ keys = rb_funcall(value, rb_intern("keys"), 0);
149
+ for(i = 0; i < RARRAY_LEN(keys); i++) {
150
+ VALUE key = RARRAY_PTR(keys)[i];
151
+ rlua_push_var(state, key);
152
+ rlua_push_var(state, rb_hash_aref(value, key));
153
+ lua_settable(state, -3);
154
+ }
155
+ break;
156
+ }
157
+
158
+ default:
159
+ if(value == Qtrue || value == Qfalse) {
160
+ lua_pushboolean(state, value == Qtrue);
161
+ } else if(rb_obj_class(value) == cLuaTable || rb_obj_class(value) == cLuaFunction) {
162
+ lua_getfield(state, LUA_REGISTRYINDEX, "rlua"); // stack: |refs|...
163
+ lua_rawgeti(state, -1, FIX2INT(rb_iv_get(value, "@ref"))); // |objt|refs|...
164
+ lua_remove(state, -2); // |objt|...
165
+ } else if(rb_obj_class(value) == cLuaState) {
166
+ lua_State* state;
167
+ Data_Get_Struct(rb_iv_get(value, "@state"), lua_State, state);
168
+ lua_pushthread(state);
169
+ } else if(rb_respond_to(value, rb_intern("call"))) {
170
+ VALUE rbLuaState;
171
+ lua_getfield(state, LUA_REGISTRYINDEX, "rlua_state");
172
+ rbLuaState = (VALUE) lua_touserdata(state, -1);
173
+ lua_pop(state, 1);
174
+
175
+ rlua_push_var(state, rb_funcall(cLuaFunction, rb_intern("new"), 2, rbLuaState, value));
176
+ } else {
177
+ rb_raise(rb_eTypeError, "wrong argument type %s", rb_obj_classname(value));
178
+ }
179
+ }
180
+ }
181
+
182
+ static const char* rlua_reader(lua_State* state, void *data, size_t *size)
183
+ {
184
+ VALUE code = (VALUE) data;
185
+
186
+ if(rb_iv_get(code, "@read") != Qnil) {
187
+ *size = 0;
188
+ return NULL;
189
+ } else {
190
+ *size = RSTRING_LEN(code);
191
+ rb_iv_set(code, "@read", Qtrue);
192
+ return RSTRING_PTR(code);
193
+ }
194
+ }
195
+
196
+ static void rlua_load_string(lua_State* state, VALUE code, VALUE chunkname)
197
+ {
198
+ Check_Type(code, T_STRING);
199
+ Check_Type(chunkname, T_STRING);
200
+
201
+ // do not interfere with users' string
202
+ VALUE interm_code = rb_str_new3(code);
203
+
204
+ int retval = lua_load(state, rlua_reader, (void*) interm_code, RSTRING_PTR(chunkname));
205
+ if(retval != 0) {
206
+ size_t errlen;
207
+ const char* errstr = lua_tolstring(state, -1, &errlen);
208
+ VALUE error = rb_str_new(errstr, errlen);
209
+ lua_pop(state, 1);
210
+ if(retval == LUA_ERRMEM)
211
+ rb_exc_raise(rb_exc_new3(rb_eNoMemError, error));
212
+ else if(retval == LUA_ERRSYNTAX)
213
+ rb_exc_raise(rb_exc_new3(rb_eSyntaxError, error));
214
+ }
215
+ }
216
+
217
+ static VALUE rlua_pcall(lua_State* state, int argc)
218
+ {
219
+ // stack: |argN-arg1|func|...
220
+ // <N pts.> <1>
221
+ int base = lua_gettop(state) - 1 - argc;
222
+
223
+ int retval = lua_pcall(state, argc, LUA_MULTRET, 0);
224
+ if(retval != 0) {
225
+ size_t errlen;
226
+ const char* errstr = lua_tolstring(state, -1, &errlen);
227
+ VALUE error = rb_str_new(errstr, errlen);
228
+ lua_pop(state, 1);
229
+
230
+ if(retval == LUA_ERRRUN)
231
+ rb_exc_raise(rb_exc_new3(rb_eRuntimeError, error));
232
+ else if(retval == LUA_ERRSYNTAX)
233
+ rb_exc_raise(rb_exc_new3(rb_eSyntaxError, error));
234
+ else
235
+ rb_fatal("unknown lua_pcall return value");
236
+ } else {
237
+ VALUE retval;
238
+ int n = lua_gettop(state) - base;
239
+ if(n == 0) {
240
+ return Qnil;
241
+ } else if(n == 1) {
242
+ retval = rlua_get_var(state);
243
+ lua_pop(state, 1);
244
+ return retval;
245
+ } else if(n > 1) {
246
+ retval = rb_ary_new();
247
+ while(n--) {
248
+ rb_ary_unshift(retval, rlua_get_var(state));
249
+ lua_pop(state, 1);
250
+ }
251
+ } else {
252
+ rb_bug("base > top!");
253
+ }
254
+ return retval;
255
+ }
256
+ }
257
+
258
+ /* :nodoc: */
259
+ static VALUE rbLuaTable_initialize(int argc, VALUE* argv, VALUE self)
260
+ {
261
+ VALUE rbLuaState, ref;
262
+ rb_scan_args(argc, argv, "11", &rbLuaState, &ref);
263
+
264
+ VALUE stateSource = rb_obj_class(rbLuaState);
265
+ if(stateSource != cLuaState && stateSource != cLuaTable && stateSource != cLuaFunction)
266
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected Lua::State, Lua::Table or Lua::Function)",
267
+ rb_obj_classname(rbLuaState));
268
+
269
+ VALUE rbState = rb_iv_get(rbLuaState, "@state");
270
+ rb_iv_set(self, "@state", rbState);
271
+
272
+ if(ref == Qnil) {
273
+ lua_State* state;
274
+ Data_Get_Struct(rbState, lua_State, state);
275
+
276
+ lua_newtable(state);
277
+ ref = rlua_makeref(state);
278
+ lua_pop(state, 1);
279
+ } else if(TYPE(ref) != T_FIXNUM) {
280
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected nil)", rb_obj_classname(ref));
281
+ }
282
+
283
+ rlua_add_ref_finalizer(rbState, ref, self);
284
+
285
+ rb_iv_set(self, "@ref", ref);
286
+
287
+ return self;
288
+ }
289
+
290
+ /*
291
+ * call-seq: Lua::Table.next(table, key) -> [ key, value ] or nil
292
+ *
293
+ * Iterates over a Lua table referenced by +table+.
294
+ * This function is analogue for Lua next function, but can be used
295
+ * even if Lua one is not defined.
296
+ *
297
+ * You can use this method yourself, through it is easier to invoke
298
+ * to_a or to_hash.
299
+ */
300
+ static VALUE rbLuaTable_next(VALUE self, VALUE table, VALUE index)
301
+ {
302
+ lua_State* state;
303
+ Data_Get_Struct(rb_iv_get(table, "@state"), lua_State, state);
304
+
305
+ VALUE retval;
306
+
307
+ rlua_push_var(state, table); // stack: |this|...
308
+ rlua_push_var(state, index); // |indx|this|...
309
+ if(lua_next(state, -2) != 0) { // |valu|key |this|...
310
+ VALUE value, key;
311
+ value = rlua_get_var(state); // |valu|key |this|...
312
+ lua_pop(state, 1); // |key |this|...
313
+ key = rlua_get_var(state); // |key |this|...
314
+ lua_pop(state, 2); // ...
315
+
316
+ retval = rb_ary_new();
317
+ rb_ary_push(retval, key);
318
+ rb_ary_push(retval, value);
319
+ } else { // |this|...
320
+ retval = Qnil;
321
+ lua_pop(state, 1); // ...
322
+ }
323
+
324
+ return retval;
325
+ }
326
+
327
+ /*
328
+ * call-seq: table[key] -> value
329
+ *
330
+ * Returns value associated with +key+ in Lua table. May invoke Lua
331
+ * +__index+ metamethod.
332
+ */
333
+ static VALUE rbLuaTable_get(VALUE self, VALUE index)
334
+ {
335
+ lua_State* state;
336
+ Data_Get_Struct(rb_iv_get(self, "@state"), lua_State, state);
337
+
338
+ VALUE value;
339
+ rlua_push_var(state, self); // stack: |this|...
340
+ rlua_push_var(state, index); // |indx|this|...
341
+ lua_gettable(state, -2); // |valu|this|...
342
+ value = rlua_get_var(state); // |valu|this|...
343
+ lua_pop(state, 2); // ...
344
+
345
+ return value;
346
+ }
347
+
348
+ /*
349
+ * call-seq: table[key] = value -> value
350
+ *
351
+ * Sets value associated with +key+ to +value+ in Lua table. May invoke Lua
352
+ * +__newindex+ metamethod.
353
+ */
354
+ static VALUE rbLuaTable_set(VALUE self, VALUE index, VALUE value)
355
+ {
356
+ lua_State* state;
357
+ Data_Get_Struct(rb_iv_get(self, "@state"), lua_State, state);
358
+
359
+ rlua_push_var(state, self); // stack: |this|...
360
+ rlua_push_var(state, index); // |indx|this|...
361
+ rlua_push_var(state, value); // |valu|indx|this|...
362
+ lua_settable(state, -3); // |this|...
363
+ lua_pop(state, 1); // ...
364
+
365
+ return value;
366
+ }
367
+
368
+ /*
369
+ * call-seq: table.__get(key) -> value
370
+ *
371
+ * Returns value associated with +key+ in Lua table without invoking
372
+ * any Lua metamethod (similar to +rawget+ Lua function).
373
+ */
374
+ static VALUE rbLuaTable_rawget(VALUE self, VALUE index)
375
+ {
376
+ lua_State* state;
377
+ Data_Get_Struct(rb_iv_get(self, "@state"), lua_State, state);
378
+
379
+ VALUE value;
380
+ rlua_push_var(state, self); // stack: |this|...
381
+ rlua_push_var(state, index); // |indx|this|...
382
+ lua_rawget(state, -2); // |valu|this|...
383
+ value = rlua_get_var(state); // |valu|this|...
384
+ lua_pop(state, 2); // ...
385
+
386
+ return value;
387
+ }
388
+
389
+ /*
390
+ * call-seq: table.__set(key, value) -> value
391
+ *
392
+ * Sets value associated with +key+ to +value+ in Lua table without invoking
393
+ * any Lua metamethod (similar to +rawset+ Lua function).
394
+ */
395
+ static VALUE rbLuaTable_rawset(VALUE self, VALUE index, VALUE value)
396
+ {
397
+ lua_State* state;
398
+ Data_Get_Struct(rb_iv_get(self, "@state"), lua_State, state);
399
+
400
+ rlua_push_var(state, self); // stack: |this|...
401
+ rlua_push_var(state, index); // |indx|this|...
402
+ rlua_push_var(state, value); // |valu|indx|this|...
403
+ lua_rawset(state, -3); // |this|...
404
+ lua_pop(state, 1); // ...
405
+
406
+ return value;
407
+ }
408
+
409
+ /*
410
+ * call-seq: table.__length -> int
411
+ *
412
+ * Returns table length as with Lua length # operator. Will not call
413
+ * any metamethod because __len metamethod has no effect when
414
+ * defined on table (and string).
415
+ */
416
+ static VALUE rbLuaTable_length(VALUE self)
417
+ {
418
+ lua_State* state;
419
+ Data_Get_Struct(rb_iv_get(self, "@state"), lua_State, state);
420
+
421
+ VALUE length;
422
+ rlua_push_var(state, self); // stack: |this|...
423
+ length = INT2FIX(lua_objlen(state, -1));
424
+ lua_pop(state, 1); // ...
425
+
426
+ return length;
427
+ }
428
+
429
+ static VALUE rbLuaFunction_call(VALUE self, VALUE args);
430
+
431
+ /*
432
+ * call-seq: table.method_missing(method, *args) -> *values
433
+ *
434
+ * This method allows accessing Lua tables much as if they were Ruby
435
+ * objects.
436
+ *
437
+ * <b>Setting values</b> can be done with a standard <i>setter method</i>:
438
+ * <tt>table.key = value</tt> is equivalent to <tt>table["key"] = value</tt>.
439
+ *
440
+ * <b>Getting values</b> is as easy as setting: if the value is not a function,
441
+ * <tt>table.key</tt> is equivalent to <tt>table["key"]</tt>.
442
+ *
443
+ * If some table has a function as value, you can <b>invoke methods</b> on it.
444
+ * <tt>table.method(arg1, ..., argN)</tt> is equivalent to
445
+ * <tt>table["method"].call(arg1, ..., argN)</tt>, and
446
+ * <tt>table.method!(arg1, ..., argN)</tt> is equivalent to
447
+ * <tt>table["method"].call(table, arg1, ..., argN)</tt>.
448
+ * To get a reference to function you should use the <tt>table["method"]</tt>
449
+ * notation.
450
+ *
451
+ */
452
+ static VALUE rbLuaTable_method_missing(int argc, VALUE* argv, VALUE self)
453
+ {
454
+ VALUE id, args;
455
+ rb_scan_args(argc, argv, "1*", &id, &args);
456
+
457
+ VALUE name = rb_str_new2(rb_id2name(rb_to_id(id)));
458
+
459
+ int is_method = 0;
460
+ int is_assign = 0;
461
+ if(RSTRING_PTR(name)[RSTRING_LEN(name) - 1] == '!')
462
+ is_method = 1;
463
+ if(RSTRING_PTR(name)[RSTRING_LEN(name) - 1] == '=')
464
+ is_assign = 1;
465
+
466
+ if(is_method || is_assign)
467
+ rb_str_resize(name, RSTRING_LEN(name) - 1);
468
+
469
+ if(is_assign) {
470
+ VALUE value;
471
+ rb_scan_args(argc, argv, "11", &id, &value);
472
+ return rbLuaTable_set(self, name, value);
473
+ } else {
474
+ VALUE value = rbLuaTable_get(self, name);
475
+ if(value == Qnil) {
476
+ return rb_call_super(argc, argv);
477
+ } else if(rb_obj_class(value) != cLuaFunction) {
478
+ if(is_method)
479
+ rb_raise(rb_eTypeError, "%s is not a Lua::Function", RSTRING_PTR(name));
480
+ return value;
481
+ } else {
482
+ if(is_method)
483
+ rb_ary_unshift(args, self);
484
+ return rbLuaFunction_call(value, args);
485
+ }
486
+ }
487
+ }
488
+
489
+ static int call_ruby_proc(lua_State* state)
490
+ {
491
+ int i;
492
+ int argc = lua_gettop(state);
493
+ VALUE proc, args;
494
+
495
+ proc = (VALUE) lua_touserdata(state, lua_upvalueindex(1));
496
+ args = rb_ary_new();
497
+
498
+ for(i = 0; i < argc; i++) {
499
+ rb_ary_unshift(args, rlua_get_var(state));
500
+ lua_pop(state, 1);
501
+ }
502
+
503
+ VALUE retval = rb_apply(proc, rb_intern("call"), args);
504
+
505
+ if(rb_obj_class(retval) == cLuaMultret) {
506
+ VALUE array = rb_iv_get(retval, "@args");
507
+ int i;
508
+
509
+ for(i = 0; i < RARRAY_LEN(array); i++)
510
+ rlua_push_var(state, RARRAY_PTR(array)[i]);
511
+
512
+ return RARRAY_LEN(array);
513
+ } else {
514
+ rlua_push_var(state, retval);
515
+ return 1;
516
+ }
517
+ }
518
+
519
+ /*
520
+ * call-seq: Lua::Function.new(state, proc)
521
+ *
522
+ * Converts a Ruby closure +proc+ to a Lua function in Lua::State represented
523
+ * by +state+. Note that you generally do not need to call this function
524
+ * explicitly: any +proc+ or +lambda+ passed as a value for table assignment
525
+ * will be automagically converted to Lua closure.
526
+ */
527
+ static VALUE rbLuaFunction_initialize(int argc, VALUE* argv, VALUE self)
528
+ {
529
+ VALUE rbLuaState, ref = Qnil, func;
530
+ rb_scan_args(argc, argv, "11", &rbLuaState, &func);
531
+
532
+ if(rb_obj_class(rbLuaState) != cLuaState)
533
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected Lua::State)", rb_obj_classname(rbLuaState));
534
+
535
+ VALUE rbState = rb_iv_get(rbLuaState, "@state");
536
+ rb_iv_set(self, "@state", rbState);
537
+
538
+ lua_State* state;
539
+ Data_Get_Struct(rbState, lua_State, state);
540
+
541
+ VALUE proc = Qnil;
542
+
543
+ if(TYPE(func) == T_FIXNUM)
544
+ ref = func;
545
+ else if(rb_respond_to(func, rb_intern("call")))
546
+ proc = func;
547
+ else
548
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected Proc)", rb_obj_classname(func));
549
+
550
+ if(ref == Qnil) {
551
+ lua_pushlightuserdata(state, (void*) proc);
552
+ lua_pushcclosure(state, call_ruby_proc, 1);
553
+ ref = rlua_makeref(state);
554
+ lua_pop(state, 1);
555
+
556
+ // don't allow GC to collect proc
557
+ rb_iv_set(self, "@proc", proc);
558
+ }
559
+
560
+ rlua_add_ref_finalizer(rbState, ref, self);
561
+
562
+ rb_iv_set(self, "@ref", ref);
563
+
564
+ return self;
565
+ }
566
+
567
+ /*
568
+ * call-seq: func.call(*args) -> *values
569
+ *
570
+ * Invokes a Lua function in protected environment (like a Lua +xpcall+).
571
+ *
572
+ * One value returned in Lua is returned as one value in Ruby; multiple values
573
+ * returned in Lua are returned as an array of them in Ruby. This convention
574
+ * allows usage of identical code for calling methods with multiple return
575
+ * values in both languages.
576
+ *
577
+ * While you can easily call Lua procedures and use their return values,
578
+ * returning multiple values from Ruby is not that easy. RLua cannot
579
+ * guess whether array returned by Ruby function is a 'real' array or
580
+ * just several return values, so there is a Lua.multret proxy method for
581
+ * that purpose. Ruby return values constructed with +multret+ method
582
+ * are automatically unpacked to multiple return values. Example:
583
+ *
584
+ * state = Lua::State.new
585
+ * state.p = lambda{ |*args| p *args }
586
+ * state.f1 = Lua::Function.new(state, lambda{ [ 1, 2, 3 ] })
587
+ * state.f2 = Lua::Function.new(state, lambda{ Lua.multret( 1, 2, 3 ) })
588
+ * state.__eval("p(f1())") # results in { 1.0, 2.0, 3.0 } Lua table
589
+ * # shown as array
590
+ * state.__eval("p(f2())") # results in 1.0, 2.0, 3.0 Lua multiple return values
591
+ * # shown as three separate values
592
+ *
593
+ * Any Lua error that has appeared during the call will be raised as Ruby
594
+ * exception with message equal to Lua error message.
595
+ * *Lua error messages are explicitly converted to strings with +lua_tostring+
596
+ * function.*
597
+ * Lua errors are mapped as follows:
598
+ * LUA_ERRMEM:: NoMemError is raised.
599
+ * LUA_ERRRUN:: RuntimeError is raised.
600
+ *
601
+ * Note that if any uncatched exception is raised in Ruby code inside
602
+ * Lua::Function it will be propagated as Lua error. *In this case the
603
+ * backtrace is lost!* Catch your exceptions in Ruby code if you want to
604
+ * keep their backtraces.
605
+ *
606
+ * This 'drawback' is intentional: while it is technically possible to
607
+ * re-raise the same Exception object, the backtrace will lead to re-raise
608
+ * point anyway.
609
+ */
610
+ static VALUE rbLuaFunction_call(VALUE self, VALUE args)
611
+ {
612
+ lua_State* state;
613
+ Data_Get_Struct(rb_iv_get(self, "@state"), lua_State, state);
614
+
615
+ int i;
616
+ VALUE retval;
617
+
618
+ rlua_push_var(state, self); // stack: |this|...
619
+ for(i = 0; i < RARRAY_LEN(args); i++)
620
+ rlua_push_var(state, RARRAY_PTR(args)[i]);
621
+ // |argN-arg1|this|...
622
+ retval = rlua_pcall(state, RARRAY_LEN(args)); // ...
623
+
624
+ return retval;
625
+ }
626
+
627
+ /*
628
+ * call-seq: Lua::State.new
629
+ *
630
+ * Creates a new Lua state.
631
+ */
632
+ static VALUE rbLua_initialize(VALUE self)
633
+ {
634
+ lua_State* state = luaL_newstate();
635
+
636
+ VALUE rbState = Data_Wrap_Struct(rb_cObject, 0, lua_close, state);
637
+ rb_iv_set(self, "@state", rbState);
638
+
639
+ lua_pushlightuserdata(state, (void*) self);
640
+ lua_setfield(state, LUA_REGISTRYINDEX, "rlua_state");
641
+
642
+ lua_newtable(state);
643
+ lua_setfield(state, LUA_REGISTRYINDEX, "rlua");
644
+
645
+ rb_iv_set(rbState, "@refs", rb_hash_new());
646
+ rb_iv_set(rbState, "@procs", rb_ary_new());
647
+
648
+ return self;
649
+ }
650
+
651
+ /*
652
+ * call-seq: state.__eval(code[, chunkname='=&lt;eval&gt;']) -> *values
653
+ *
654
+ * Runs +code+ in Lua interpreter. Optional argument +chunkname+
655
+ * specifies a string that will be used in error messages and other
656
+ * debug information as a file name.
657
+ *
658
+ * Start +chunkname+ with a @ to make Lua think the following is filename
659
+ * (e.g. @test.lua); start it with a = to indicate a non-filename stream
660
+ * (e.g. =stdin). Anything other is interpreted as a plaintext Lua code and
661
+ * a few starting characters will be shown.
662
+ */
663
+ static VALUE rbLua_eval(int argc, VALUE* argv, VALUE self)
664
+ {
665
+ VALUE code, chunkname;
666
+ rb_scan_args(argc, argv, "11", &code, &chunkname);
667
+
668
+ lua_State* state;
669
+ Data_Get_Struct(rb_iv_get(self, "@state"), lua_State, state);
670
+
671
+ if(chunkname == Qnil)
672
+ chunkname = rb_str_new2("=<eval>");
673
+
674
+ rlua_load_string(state, code, chunkname);
675
+
676
+ return rlua_pcall(state, 0);
677
+ }
678
+
679
+ /*
680
+ * call-seq: object.__env() -> Lua::Table
681
+ *
682
+ * Returns environment table of Lua::State or Lua::Function.
683
+ */
684
+ static VALUE rbLua_get_env(VALUE self)
685
+ {
686
+ lua_State* state;
687
+ Data_Get_Struct(rb_iv_get(self, "@state"), lua_State, state);
688
+
689
+ VALUE ref;
690
+ rlua_push_var(state, self); // stack: |this|...
691
+ lua_getfenv(state, -1); // |envi|this|...
692
+ ref = rlua_makeref(state); // |envi|this|...
693
+ lua_pop(state, 2); // ...
694
+
695
+ return rb_funcall(cLuaTable, rb_intern("new"), 2, self, ref);
696
+ }
697
+
698
+ /*
699
+ * call-seq: object.__env=(table) -> table
700
+ *
701
+ * Sets environment table for Lua::State or Lua::Function. +table+ may be
702
+ * a Lua::Table or a Hash.
703
+ */
704
+ static VALUE rbLua_set_env(VALUE self, VALUE env)
705
+ {
706
+ lua_State* state;
707
+ Data_Get_Struct(rb_iv_get(self, "@state"), lua_State, state);
708
+
709
+ if(rb_obj_class(env) != cLuaTable && TYPE(env) != T_HASH)
710
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected Lua::Table or Hash)", rb_obj_classname(env));
711
+
712
+ rlua_push_var(state, self); // stack: |this|...
713
+ rlua_push_var(state, env); // |envi|this|...
714
+ lua_setfenv(state, -2); // |this|...
715
+ lua_pop(state, 1); // ...
716
+
717
+ return env;
718
+ }
719
+
720
+ /*
721
+ * call-seq: state.__get_metatable(object) -> Lua::Table or nil
722
+ *
723
+ * Returns metatable of any valid Lua object or nil if it is not present.
724
+ * If you want to get metatables of non-table objects (e.g. numbers)
725
+ * just pass their Ruby equivalent.
726
+ */
727
+ static VALUE rbLua_get_metatable(VALUE self, VALUE object)
728
+ {
729
+ lua_State* state;
730
+ Data_Get_Struct(rb_iv_get(self, "@state"), lua_State, state);
731
+
732
+ rlua_push_var(state, object); // stack: |objt|...
733
+ if(lua_getmetatable(state, -1)) { // |meta|objt|...
734
+ VALUE ref = rlua_makeref(state); // |meta|objt|...
735
+ lua_pop(state, 2); // ...
736
+
737
+ return rb_funcall(cLuaTable, rb_intern("new"), 2, self, ref);
738
+ } else { // |objt|...
739
+ lua_pop(state, 1); // ...
740
+
741
+ return Qnil;
742
+ }
743
+ }
744
+
745
+ /*
746
+ * call-seq: state.__set_metatable=(object, metatable) -> metatable
747
+ *
748
+ * Sets metatable for any valid Lua object. +metatable+ can be Lua::Table or
749
+ * Hash. If you want to set metatables for non-table objects (e.g. numbers)
750
+ * just pass their Ruby equivalent.
751
+ *
752
+ * # Implement concatenation operator for Lua strnigs.
753
+ * state = Lua::State.new
754
+ * state.__set_metatable("", { '__add' => lambda{ |a, b| a + b } })
755
+ * p state.__eval('return "hello," + " world"') # => "hello, world"
756
+ */
757
+ static VALUE rbLua_set_metatable(VALUE self, VALUE object, VALUE metatable)
758
+ {
759
+ lua_State* state;
760
+ Data_Get_Struct(rb_iv_get(self, "@state"), lua_State, state);
761
+
762
+ if(rb_obj_class(metatable) != cLuaTable && TYPE(metatable) != T_HASH)
763
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected Lua::Table or Hash)", rb_obj_classname(metatable));
764
+
765
+ rlua_push_var(state, object); // stack: |objt|...
766
+ rlua_push_var(state, metatable); // |meta|objt|...
767
+ lua_setmetatable(state, -2); // |objt|...
768
+ lua_pop(state, 1); // ...
769
+
770
+ return metatable;
771
+ }
772
+
773
+ /*
774
+ * call-seq: table.__metatable() -> Lua::Table or nil
775
+ *
776
+ * Returns metatable of this table or nil if it is not present.
777
+ */
778
+ static VALUE rbLuaTable_get_metatable(VALUE self)
779
+ {
780
+ return rbLua_get_metatable(self, self);
781
+ }
782
+
783
+ /*
784
+ * call-seq: table.__metatable=(metatable) -> metatable
785
+ *
786
+ * Sets metatable for this table. +metatable+ can be Lua::Table or Hash.
787
+ */
788
+ static VALUE rbLuaTable_set_metatable(VALUE self, VALUE metatable)
789
+ {
790
+ return rbLua_set_metatable(self, self, metatable);
791
+ }
792
+
793
+ /*
794
+ * call-seq: state[key] -> value
795
+ *
796
+ * Returns value of a global variable. Equivalent to __env[key].
797
+ */
798
+ static VALUE rbLua_get_global(VALUE self, VALUE index)
799
+ {
800
+ VALUE globals = rbLua_get_env(self);
801
+ return rbLuaTable_get(globals, index);
802
+ }
803
+
804
+ /*
805
+ * call-seq: state[key] = value -> value
806
+ *
807
+ * Sets value for a global variable. Equivalent to __env[key] = value.
808
+ */
809
+ static VALUE rbLua_set_global(VALUE self, VALUE index, VALUE value)
810
+ {
811
+ return rbLuaTable_set(rbLua_get_env(self), index, value);
812
+ }
813
+
814
+ /*
815
+ * call-seq: this == other -> true or false
816
+ *
817
+ * Compares +this+ with +other+. May call +__eq+ metamethod.
818
+ */
819
+ static VALUE rbLua_equal(VALUE self, VALUE other)
820
+ {
821
+ lua_State* state;
822
+ Data_Get_Struct(rb_iv_get(self, "@state"), lua_State, state);
823
+
824
+ int equal;
825
+ rlua_push_var(state, self); // stack: |this|...
826
+ rlua_push_var(state, other); // |othr|this|...
827
+ equal = lua_equal(state, -1, -2); // |othr|this|...
828
+ lua_pop(state, 2); // ...
829
+
830
+ return equal ? Qtrue : Qfalse;
831
+ }
832
+
833
+ /*
834
+ * call-seq: this.__equal(other) -> true or false
835
+ *
836
+ * Compares +this+ with +other+ without calling any metamethods.
837
+ */
838
+ static VALUE rbLua_rawequal(VALUE self, VALUE other)
839
+ {
840
+ lua_State* state;
841
+ Data_Get_Struct(rb_iv_get(self, "@state"), lua_State, state);
842
+
843
+ int equal;
844
+ rlua_push_var(state, self); // stack: |this|...
845
+ rlua_push_var(state, other); // |othr|this|...
846
+ equal = lua_rawequal(state, -1, -2); // |othr|this|...
847
+ lua_pop(state, 2); // ...
848
+
849
+ return equal ? Qtrue : Qfalse;
850
+ }
851
+
852
+ /*
853
+ * call-seq: state.method_missing(method, *args) -> *values
854
+ *
855
+ * See Lua::Table#method_missing. Equivalent to __env.method_missing(method, *args).
856
+ */
857
+ static VALUE rbLua_method_missing(int argc, VALUE* argv, VALUE self)
858
+ {
859
+ return rbLuaTable_method_missing(argc, argv, rbLua_get_env(self));
860
+ }
861
+
862
+ /*
863
+ * call-seq: Lua::Multret.new(*values)
864
+ *
865
+ * Creates a new Multret object with +values+ inside. Example:
866
+ *
867
+ * Lua::Multret.new(1, 2, 3) # three return values
868
+ */
869
+ static VALUE rbLuaMultret_initialize(VALUE self, VALUE args)
870
+ {
871
+ rb_iv_set(self, "@args", args);
872
+ return self;
873
+ }
874
+
875
+ /*
876
+ * call-seq: Lua.multret(*values)
877
+ *
878
+ * Shorthand for Lua::Multret.new.
879
+ */
880
+ static VALUE rbLua_multret(VALUE self, VALUE args)
881
+ {
882
+ return rb_funcall(cLuaMultret, rb_intern("new"), 1, args);
883
+ }
884
+
885
+ // bootstrap* are from Lua5.1 source
886
+
887
+ static int bootstrap_tonumber (lua_State *L) {
888
+ int base = luaL_optint(L, 2, 10);
889
+ if (base == 10) { /* standard conversion */
890
+ luaL_checkany(L, 1);
891
+ if (lua_isnumber(L, 1)) {
892
+ lua_pushnumber(L, lua_tonumber(L, 1));
893
+ return 1;
894
+ }
895
+ }
896
+ else {
897
+ const char *s1 = luaL_checkstring(L, 1);
898
+ char *s2;
899
+ unsigned long n;
900
+ luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
901
+ n = strtoul(s1, &s2, base);
902
+ if (s1 != s2) { /* at least one valid digit? */
903
+ while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */
904
+ if (*s2 == '\0') { /* no invalid trailing characters? */
905
+ lua_pushnumber(L, (lua_Number)n);
906
+ return 1;
907
+ }
908
+ }
909
+ }
910
+ lua_pushnil(L); /* else not a number */
911
+ return 1;
912
+ }
913
+
914
+ static int bootstrap_tostring (lua_State *L) {
915
+ luaL_checkany(L, 1);
916
+ if (luaL_callmeta(L, 1, "__tostring")) /* is there a metafield? */
917
+ return 1; /* use its value */
918
+ switch (lua_type(L, 1)) {
919
+ case LUA_TNUMBER:
920
+ lua_pushstring(L, lua_tostring(L, 1));
921
+ break;
922
+ case LUA_TSTRING:
923
+ lua_pushvalue(L, 1);
924
+ break;
925
+ case LUA_TBOOLEAN:
926
+ lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false"));
927
+ break;
928
+ case LUA_TNIL:
929
+ lua_pushliteral(L, "nil");
930
+ break;
931
+ default:
932
+ lua_pushfstring(L, "%s: %p", luaL_typename(L, 1), lua_topointer(L, 1));
933
+ break;
934
+ }
935
+ return 1;
936
+ }
937
+
938
+ static int bootstrap_error (lua_State *L) {
939
+ int level = luaL_optint(L, 2, 1);
940
+ lua_settop(L, 1);
941
+ if (lua_isstring(L, 1) && level > 0) { /* add extra information? */
942
+ luaL_where(L, level);
943
+ lua_pushvalue(L, 1);
944
+ lua_concat(L, 2);
945
+ }
946
+ return lua_error(L);
947
+ }
948
+
949
+ static int bootstrap_type (lua_State *L) {
950
+ luaL_checkany(L, 1);
951
+ lua_pushstring(L, luaL_typename(L, 1));
952
+ return 1;
953
+ }
954
+
955
+
956
+ static int bootstrap_next (lua_State *L) {
957
+ luaL_checktype(L, 1, LUA_TTABLE);
958
+ lua_settop(L, 2); /* create a 2nd argument if there isn't one */
959
+ if (lua_next(L, 1))
960
+ return 2;
961
+ else {
962
+ lua_pushnil(L);
963
+ return 1;
964
+ }
965
+ }
966
+
967
+
968
+ static int bootstrap_pairs (lua_State *L) {
969
+ luaL_checktype(L, 1, LUA_TTABLE);
970
+ lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */
971
+ lua_pushvalue(L, 1); /* state, */
972
+ lua_pushnil(L); /* and initial value */
973
+ return 3;
974
+ }
975
+
976
+
977
+ static int bootstrap_inext (lua_State *L) {
978
+ int i = luaL_checkint(L, 2);
979
+ luaL_checktype(L, 1, LUA_TTABLE);
980
+ i++; /* next value */
981
+ lua_pushinteger(L, i);
982
+ lua_rawgeti(L, 1, i);
983
+ return (lua_isnil(L, -1)) ? 0 : 2;
984
+ }
985
+
986
+
987
+ static int bootstrap_ipairs (lua_State *L) {
988
+ luaL_checktype(L, 1, LUA_TTABLE);
989
+ lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */
990
+ lua_pushvalue(L, 1); /* state, */
991
+ lua_pushinteger(L, 0); /* and initial value */
992
+ return 3;
993
+ }
994
+
995
+ static int bootstrap_unpack (lua_State *L) {
996
+ int i, e, n;
997
+ luaL_checktype(L, 1, LUA_TTABLE);
998
+ i = luaL_optint(L, 2, 1);
999
+ e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1));
1000
+ n = e - i + 1; /* number of elements */
1001
+ if (n <= 0) return 0; /* empty range */
1002
+ luaL_checkstack(L, n, "table too big to unpack");
1003
+ for (; i<=e; i++) /* push arg[i...e] */
1004
+ lua_rawgeti(L, 1, i);
1005
+ return n;
1006
+ }
1007
+
1008
+
1009
+ static int bootstrap_select (lua_State *L) {
1010
+ int n = lua_gettop(L);
1011
+ if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') {
1012
+ lua_pushinteger(L, n-1);
1013
+ return 1;
1014
+ }
1015
+ else {
1016
+ int i = luaL_checkint(L, 1);
1017
+ if (i < 0) i = n + i;
1018
+ else if (i > n) i = n;
1019
+ luaL_argcheck(L, 1 <= i, 1, "index out of range");
1020
+ return n - i;
1021
+ }
1022
+ }
1023
+
1024
+ static int bootstrap_assert (lua_State *L) {
1025
+ luaL_checkany(L, 1);
1026
+ if (!lua_toboolean(L, 1))
1027
+ return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!"));
1028
+ return lua_gettop(L);
1029
+ }
1030
+
1031
+ static int bootstrap_pcall (lua_State *L) {
1032
+ int status;
1033
+ luaL_checkany(L, 1);
1034
+ status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0);
1035
+ lua_pushboolean(L, (status == 0));
1036
+ lua_insert(L, 1);
1037
+ return lua_gettop(L); /* return status + all results */
1038
+ }
1039
+
1040
+ static int bootstrap_xpcall (lua_State *L) {
1041
+ int status;
1042
+ luaL_checkany(L, 2);
1043
+ lua_settop(L, 2);
1044
+ lua_insert(L, 1); /* put error function under function to be called */
1045
+ status = lua_pcall(L, 0, LUA_MULTRET, 1);
1046
+ lua_pushboolean(L, (status == 0));
1047
+ lua_replace(L, 1);
1048
+ return lua_gettop(L); /* return status + all results */
1049
+ }
1050
+
1051
+ static const
1052
+ struct { char* name; lua_CFunction func; }
1053
+ stdlib[] = {
1054
+ { "type", bootstrap_type },
1055
+ { "next", bootstrap_next },
1056
+ { "tonumber", bootstrap_tonumber },
1057
+ { "tostring", bootstrap_tostring },
1058
+ { "unpack", bootstrap_unpack },
1059
+ { "select", bootstrap_select },
1060
+ { "error", bootstrap_error },
1061
+ { "assert", bootstrap_assert },
1062
+ { "pcall", bootstrap_pcall },
1063
+ { "xpcall", bootstrap_xpcall },
1064
+ };
1065
+
1066
+ /*
1067
+ * call-seq: state.__bootstrap() -> true
1068
+ *
1069
+ * Deploys an absolute minimum of functions required to write minimally
1070
+ * useful Lua programs. This is really a subset of Lua _base_ library
1071
+ * (copied from Lua 5.1 sources) that may be handy if you don't like standard
1072
+ * function layout. All of these functions can be implemented in pure Ruby,
1073
+ * but that will slow down Lua code incredibly.
1074
+ *
1075
+ * <b>If you want to get familiar layout described in Lua documentation, check
1076
+ * #__load_stdlib function.</b>
1077
+ *
1078
+ * Exact list of functions defined: type, next, tonumber, tostring, unpack,
1079
+ * select, error, assert, pcall, xpcall.
1080
+ */
1081
+ static VALUE rbLua_bootstrap(VALUE self)
1082
+ {
1083
+ lua_State* state;
1084
+ Data_Get_Struct(rb_iv_get(self, "@state"), lua_State, state);
1085
+
1086
+ int nf;
1087
+ for(nf = 0; nf < sizeof(stdlib) / sizeof(stdlib[0]); nf++) {
1088
+ lua_pushcclosure(state, stdlib[nf].func, 0);
1089
+ lua_setglobal(state, stdlib[nf].name);
1090
+ }
1091
+
1092
+ lua_pushcfunction(state, bootstrap_next);
1093
+ lua_pushcclosure(state, bootstrap_pairs, 1);
1094
+ lua_setglobal(state, "pairs");
1095
+
1096
+ lua_pushcfunction(state, bootstrap_inext);
1097
+ lua_pushcclosure(state, bootstrap_ipairs, 1);
1098
+ lua_setglobal(state, "ipairs");
1099
+
1100
+ return Qtrue;
1101
+ }
1102
+
1103
+ static void rlua_openlib(lua_State* state, lua_CFunction func)
1104
+ {
1105
+ lua_pushcfunction(state, func);
1106
+ lua_call(state, 0, 0);
1107
+ }
1108
+
1109
+ /*
1110
+ * call-seq: state.__load_stdlib(*libs) -> true
1111
+ *
1112
+ * Loads Lua standard libraries. There are two ways of calling this function:
1113
+ *
1114
+ * If you will call it as __load_stdlib(:all), it is equivalent to calling
1115
+ * C +luaL_openlibs+ function.
1116
+ *
1117
+ * If you will pass it symbolized names of separate libraries (like :base),
1118
+ * it is equivalent to calling corresponding +luaopen_*+ functions.
1119
+ *
1120
+ * Examples:
1121
+ *
1122
+ * # Load all standard libraries
1123
+ * state = Lua::State.new
1124
+ * state.__load_stdlib :all
1125
+ *
1126
+ * # Load only math, string and table libraries
1127
+ * state = Lua::State.new
1128
+ * state.__load_stdlib :math, :string, :table
1129
+ *
1130
+ * Exact list of libraries recognized: <tt>:base</tt>, <tt>:table</tt>,
1131
+ * <tt>:math</tt>, <tt>:string</tt>, <tt>:debug</tt>, <tt>:io</tt>,
1132
+ * <tt>:os</tt>, <tt>:package</tt>.
1133
+ * <b>Anything not included in this list will be silently ignored.</b>
1134
+ */
1135
+ static VALUE rbLua_load_stdlib(VALUE self, VALUE args)
1136
+ {
1137
+ lua_State* state;
1138
+ Data_Get_Struct(rb_iv_get(self, "@state"), lua_State, state);
1139
+
1140
+ if(rb_ary_includes(args, ID2SYM(rb_intern("all")))) {
1141
+ luaL_openlibs(state);
1142
+ } else {
1143
+ if(rb_ary_includes(args, ID2SYM(rb_intern("base"))))
1144
+ rlua_openlib(state, luaopen_base);
1145
+ if(rb_ary_includes(args, ID2SYM(rb_intern(LUA_TABLIBNAME))))
1146
+ rlua_openlib(state, luaopen_table);
1147
+ if(rb_ary_includes(args, ID2SYM(rb_intern(LUA_MATHLIBNAME))))
1148
+ rlua_openlib(state, luaopen_math);
1149
+ if(rb_ary_includes(args, ID2SYM(rb_intern(LUA_STRLIBNAME))))
1150
+ rlua_openlib(state, luaopen_string);
1151
+ if(rb_ary_includes(args, ID2SYM(rb_intern(LUA_DBLIBNAME))))
1152
+ rlua_openlib(state, luaopen_debug);
1153
+ if(rb_ary_includes(args, ID2SYM(rb_intern(LUA_IOLIBNAME))))
1154
+ rlua_openlib(state, luaopen_io);
1155
+ if(rb_ary_includes(args, ID2SYM(rb_intern(LUA_OSLIBNAME))))
1156
+ rlua_openlib(state, luaopen_os);
1157
+ if(rb_ary_includes(args, ID2SYM(rb_intern(LUA_LOADLIBNAME))))
1158
+ rlua_openlib(state, luaopen_package);
1159
+ }
1160
+
1161
+ return Qtrue;
1162
+ }
1163
+
1164
+ void Init_rlua()
1165
+ {
1166
+ /*
1167
+ * Main module that encapsulates all RLua classes and methods.
1168
+ */
1169
+ mLua = rb_define_module("Lua");
1170
+
1171
+ /*
1172
+ * Lua::State represents Lua interpreter state which is one thread of
1173
+ * execution.
1174
+ */
1175
+ cLuaState = rb_define_class_under(mLua, "State", rb_cObject);
1176
+ rb_define_method(cLuaState, "initialize", rbLua_initialize, 0);
1177
+ rb_define_method(cLuaState, "__eval", rbLua_eval, -1);
1178
+ rb_define_method(cLuaState, "__bootstrap", rbLua_bootstrap, 0);
1179
+ rb_define_method(cLuaState, "__load_stdlib", rbLua_load_stdlib, -2);
1180
+ rb_define_method(cLuaState, "__env", rbLua_get_env, 0);
1181
+ rb_define_method(cLuaState, "__env=", rbLua_set_env, 1);
1182
+ rb_define_method(cLuaState, "__get_metatable", rbLua_get_metatable, 1);
1183
+ rb_define_method(cLuaState, "__set_metatable", rbLua_set_metatable, 2);
1184
+ rb_define_method(cLuaState, "[]", rbLua_get_global, 1);
1185
+ rb_define_method(cLuaState, "[]=", rbLua_set_global, 2);
1186
+ rb_define_method(cLuaState, "method_missing", rbLua_method_missing, -1);
1187
+
1188
+ /*
1189
+ * An intermediate object assisting return of multiple values from Ruby.
1190
+ * See description of Lua::Function#call.
1191
+ */
1192
+ cLuaMultret = rb_define_class_under(mLua, "Multret", rb_cObject);
1193
+ rb_define_method(cLuaMultret, "initialize", rbLuaMultret_initialize, 1);
1194
+ rb_define_singleton_method(mLua, "multret", rbLua_multret, -2);
1195
+
1196
+ /*
1197
+ * Lua::Function represents a Lua function, may it be a native (i.e.
1198
+ * defined in Lua code) function or Ruby closure.
1199
+ *
1200
+ * Lua::Function is duck-typed like a +proc+ (implements +call+ method)
1201
+ * and thus can be used as a replacement, through it cannot be converted
1202
+ * to block. You can use
1203
+ *
1204
+ * some_method(parameters) { |*args| lua_func.call(*args) }
1205
+ *
1206
+ * instead.
1207
+ *
1208
+ * See also important notes about exceptions and return values in
1209
+ * #call function.
1210
+ */
1211
+ cLuaFunction = rb_define_class_under(mLua, "Function", rb_cObject);
1212
+ rb_define_method(cLuaFunction, "initialize", rbLuaFunction_initialize, -1);
1213
+ rb_define_method(cLuaFunction, "call", rbLuaFunction_call, -2);
1214
+ rb_define_method(cLuaFunction, "__env", rbLua_get_env, 0);
1215
+ rb_define_method(cLuaFunction, "__env=", rbLua_set_env, 1);
1216
+ rb_define_method(cLuaFunction, "__equal", rbLua_rawequal, 1);
1217
+ rb_define_method(cLuaFunction, "==", rbLua_equal, 1);
1218
+
1219
+ /*
1220
+ * A Ruby Lua::Table object represents a *reference* to a Lua table.
1221
+ * As it is a reference, any changes made to table in Lua are visible in
1222
+ * Ruby and vice versa.
1223
+ *
1224
+ * See also #method_missing function for a convenient way to access tables.
1225
+ */
1226
+ cLuaTable = rb_define_class_under(mLua, "Table", rb_cObject);
1227
+ rb_define_singleton_method(cLuaTable, "next", rbLuaTable_next, 2);
1228
+ rb_define_method(cLuaTable, "initialize", rbLuaTable_initialize, -1);
1229
+ rb_define_method(cLuaTable, "__metatable", rbLuaTable_get_metatable, 0);
1230
+ rb_define_method(cLuaTable, "__metatable=", rbLuaTable_set_metatable, 1);
1231
+ rb_define_method(cLuaTable, "__length", rbLuaTable_length, 0);
1232
+ rb_define_method(cLuaTable, "__get", rbLuaTable_rawget, 1);
1233
+ rb_define_method(cLuaTable, "__set", rbLuaTable_rawset, 2);
1234
+ rb_define_method(cLuaTable, "__equal", rbLua_rawequal, 1);
1235
+ rb_define_method(cLuaTable, "[]", rbLuaTable_get, 1);
1236
+ rb_define_method(cLuaTable, "[]=", rbLuaTable_set, 2);
1237
+ rb_define_method(cLuaTable, "==", rbLua_equal, 1);
1238
+ rb_define_method(cLuaTable, "method_missing", rbLuaTable_method_missing, -1);
1239
+ }