9 #include "../../libs/pbd/pbd/reallocpool.h"
10 #include "../../libs/pbd/reallocpool.cc"
12 #include <readline/readline.h>
13 #include <readline/history.h>
15 #include "lua/luastate.h"
16 #include "LuaBridge/LuaBridge.h"
18 static void my_lua_print (std::string s) {
19 std::cout << s << "\n";
22 luabridge::LuaRef::Proxy&
23 luabridge::LuaRef::Proxy::clone_instance (const void* classkey, void* p) {
24 lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_tableRef);
25 lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_keyRef);
27 luabridge::UserdataPtr::push_raw (m_L, p, classkey);
38 A() { printf ("CTOR %p\n", this); _int = 4; for (int i = 0; i < 256; ++i) {arr[i] = i; ar2[i] = i/256.0; ar3[i] = i;} }
39 ~A() { printf ("DTOR\n"); }
41 void set_int (int a) { _int = a; }
42 int get_int () const { return _int; }
44 int& get_ref () { return _int; }
45 int get_arg (int &a) { printf ("a = %d\n", a); a = _int; printf ("a = %d\n", a); return 1; }
46 void get_arg2 (int &a, int& b) { a = _int; b = 100; }
47 void get_args (std::string &a) { a = "hello"; }
48 void set_ref (int const &a) { _int = a; }
50 float * get_arr () { return arr; }
51 float * get_ar2 () { return ar2; }
52 int * get_ar3 () { return ar3; }
54 void set_list (std::list<std::string> sl) { _sl = sl; }
55 std::list<std::string>& get_list () { return _sl; }
57 uint32_t minone() { return -1; }
58 void pointer (float*f) const { printf ("PTR %p", f); }
64 enum EN ret_enum () { return _en;}
65 void set_enum (enum EN en) { _en = en; }
68 std::list<std::string> _sl;
82 int get (lua_State* L) {
83 luabridge::LuaRef rv (luabridge::newTable (L));
84 for (std::vector<LuaTableEntry>::const_iterator i = _data.begin (); i != _data.end (); ++i) {
85 switch ((*i).keytype) {
87 assign(&rv, i->k_s, *i);
90 assign(&rv, i->k_n, *i);
94 luabridge::push (L, rv);
98 int set (lua_State* L) {
99 if (!lua_istable (L, -1)) { return luaL_error (L, "argument is not a table"); }
102 lua_pushvalue (L, -1);
104 while (lua_next (L, -2)) {
105 lua_pushvalue (L, -2);
107 LuaTableEntry s (lua_type(L, -1), lua_type(L, -2));
108 switch (lua_type(L, -1)) {
110 s.k_s = luabridge::Stack<std::string>::get (L, -1);
114 s.k_n = luabridge::Stack<unsigned int>::get (L, -1);
122 switch(lua_type(L, -2)) {
124 s.s = luabridge::Stack<std::string>::get (L, -2);
127 s.b = lua_toboolean (L, -2);
130 s.n = lua_tonumber (L, -2);
135 lua_getmetatable (L, -2);
136 lua_rawgetp (L, -1, luabridge::getIdentityKey ());
137 if (lua_isboolean (L, -1)) {
139 const void* key = lua_topointer (L, -1);
141 void const* classkey = findclasskey (L, key);
146 s.p = luabridge::Userdata::get_ptr (L, -2);
155 // invalid userdata -- fall through
158 case LUA_TFUNCTION: // no support -- we could... string.format("%q", string.dump(value, true))
159 case LUA_TTABLE: // no nested tables, sorry.
160 case LUA_TNIL: // fallthrough
173 static void* findclasskey (lua_State *L, const void* key)
175 lua_pushvalue(L, LUA_REGISTRYINDEX);
177 while (lua_next (L, -2)) {
178 lua_pushvalue (L, -2);
179 if (lua_topointer(L, -2) == key) {
180 void* rv = lua_touserdata (L, -1);
191 struct LuaTableEntry {
192 LuaTableEntry (int kt, int vt)
214 static void assign (luabridge::LuaRef* rv, T key, const LuaTableEntry& s)
216 switch (s.valuetype) {
227 (*rv)[key].clone_instance (s.c, s.p);
235 std::vector<LuaTableEntry> _data;
240 static void* findclasskey (lua_State *L, const void* key)
242 lua_pushvalue(L, LUA_REGISTRYINDEX);
244 while (lua_next (L, -2)) {
245 lua_pushvalue (L, -2);
246 if (lua_topointer(L, -2) == key) {
247 void* rv = lua_touserdata (L, -1);
257 static int tableSerialize (lua_State *L)
259 if (!lua_istable (L, -1)) { return luaL_error (L, "argument is not a table"); }
261 luabridge::LuaRef rv (luabridge::newTable (L));
262 std::cout << "CLASS A KEY: " << luabridge::ClassInfo <A>::getClassKey () << "\n";
263 lua_rawgetp (L, LUA_REGISTRYINDEX, luabridge::ClassInfo <A>::getClassKey ());
264 std::cout << " CLASS A TABLE PTR=" << lua_topointer (L, -1) << "\n";
266 // for k,v in pairs (debug.getregistry ()) do print (k,v) end
268 lua_pushvalue (L, -1);
270 while (lua_next (L, -2)) {
271 lua_pushvalue (L, -2);
272 unsigned int const i = luabridge::Stack<unsigned int>::get (L, -1);
273 int t = lua_type(L, -2);
276 std::cout << " " << i << ": '" << lua_tostring(L, -2) << "'\n";
277 rv[i] = lua_tostring(L, -2);
280 std::cout << " " << i << ": " <<
281 (lua_toboolean(L, -2) ? "true" : "false") << "\n";
282 rv[i] = lua_toboolean(L, -2);
285 std::cout << " " << i << ": " << lua_tonumber(L, -2) << "\n";
286 rv[i] = lua_tonumber(L, -2);
290 lua_getmetatable (L, -2);
291 lua_rawgetp (L, -1, luabridge::getIdentityKey ());
292 if (lua_isboolean (L, -1)) {
294 const void* key = lua_topointer (L, -1);
296 void const* classkey = findclasskey (L, key);
299 void* p = luabridge::Userdata::get_ptr (L, -2);
300 rv[i].clone_instance (classkey, p);
310 case LUA_TLIGHTUSERDATA:
312 std::cout << " " << i << ": TYPE=" << t << ": " << lua_topointer(L, -2)<< "\n";
320 luabridge::push (L, rv);
325 LuaTableRef globalref;
327 int runone (LuaState& lua)
330 LuaState lua (*new LuaState);
332 PBD::ReallocPool _mempool ("Devel", 1048576);
333 LuaState lua (lua_newstate (&PBD::ReallocPool::lalloc, &_mempool));
335 lua.Print.connect (&my_lua_print);
336 lua_State* L = lua.getState();
340 luabridge::getGlobalNamespace (L)
341 .beginNamespace ("Test")
342 .beginStdList <std::string> ("StringList")
346 luabridge::getGlobalNamespace (L)
347 .beginNamespace ("Test")
348 .beginStdVector <std::string> ("StringVector")
352 luabridge::getGlobalNamespace (L)
353 .beginNamespace ("Test")
354 .beginStdMap <std::string,std::string> ("StringStringMap")
358 luabridge::getGlobalNamespace (L)
359 .beginNamespace ("Test")
360 .beginStdSet <std::string> ("StringSet")
365 luabridge::getGlobalNamespace (L)
366 .beginNamespace ("Test")
367 .registerArray <float> ("FloatArray")
368 .registerArray <int> ("IntArray")
369 .beginClass <A> ("A")
370 .addConstructor <void (*) ()> ()
371 .addFunction ("set_int", &A::set_int)
372 .addFunction ("get_int", &A::get_int)
373 .addRefFunction ("get_arg", &A::get_arg)
374 .addRefFunction ("get_arg2", &A::get_arg2)
375 .addRefFunction ("get_args", &A::get_args)
376 .addFunction ("set_ref", &A::set_ref)
377 .addFunction ("get_list", &A::get_list)
378 .addFunction ("set_list", &A::set_list)
379 .addFunction ("ret_enum", &A::ret_enum)
380 .addFunction ("set_enum", &A::set_enum)
381 .addFunction ("get_arr", &A::get_arr)
382 .addFunction ("get_ar2", &A::get_ar2)
383 .addFunction ("get_ar3", &A::get_ar3)
387 luabridge::getGlobalNamespace (L)
388 .beginNamespace ("Test")
389 .beginClass <A> ("A")
390 .addFunction ("pointer", &A::pointer)
391 .addFunction ("minone", &A::minone)
392 .addConst ("cologne", 4711)
394 .addConst ("koln", 4711)
397 luabridge::getGlobalNamespace (L)
398 .beginNamespace ("Dump")
400 .beginClass <LuaTableRef> ("TableRef")
401 .addCFunction ("get", &LuaTableRef::get)
402 .addCFunction ("set", &LuaTableRef::set)
405 //.addCFunction ("dump", tableSerialize)
408 luabridge::push <LuaTableRef *> (L, &globalref);
409 lua_setglobal (L, "ref");
412 #if 0 // session script test
414 "function ArdourSession ()"
415 " local self = { scripts = {}, instances = {} }"
417 " local foreach = function (fn)"
418 " for n, s in pairs (self.scripts) do"
423 " local run = function ()"
424 " for n, s in pairs (self.instances) do"
425 " local status, err = pcall (s)"
426 " if not status then print ('fn \"'.. n .. '\": ', err) end"
431 " local add = function (n, f, a)"
432 " assert(type(n) == 'string', 'function-name must be string')"
433 " assert(type(f) == 'function', 'Given script is a not a function')"
434 " assert(type(a) == 'table' or type(a) == 'nil', 'Given argument is invalid')"
435 " assert(self.scripts[n] == nil, 'Callback \"'.. n ..'\" already exists.')"
436 " self.scripts[n] = { ['f'] = f, ['a'] = a }"
437 " local env = { print = print, Session = Session, tostring = tostring, assert = assert, ipairs = ipairs, error = error, string = string, type = type, tonumber = tonumber, collectgarbage = collectgarbage, pairs = pairs, math = math, table = table, pcall = pcall }"
438 " self.instances[n] = load (string.dump(f), nil, nil, env)(a)"
441 " local remove = function (n)"
442 " self.scripts[n] = nil"
445 " local list = function ()"
447 " foreach (function (n) rv[n] = true end)"
451 " local function basic_serialize (o)"
452 " if type(o) == \"number\" then"
453 " return tostring(o)"
455 " return string.format(\"%q\", o)"
459 " local function serialize (name, value)"
460 " local rv = name .. ' = '"
461 " if type(value) == \"number\" or type(value) == \"string\" or type(value) == \"nil\" then"
462 " return rv .. basic_serialize(value) .. ' '"
463 " elseif type(value) == \"table\" then"
465 " for k,v in pairs(value) do"
466 " local fieldname = string.format(\"%s[%s]\", name, basic_serialize(k))"
467 " rv = rv .. serialize(fieldname, v) .. ' '"
470 " elseif type(value) == \"function\" then"
471 " return rv .. string.format(\"%q\", string.dump(value))"
473 " error('cannot save a ' .. type(value))"
478 " local save = function ()"
479 " return (serialize('scripts', self.scripts))"
482 " local restore = function (state)"
486 " for n, s in pairs (scripts) do"
487 " add (n, load(s['f']), s['a'])"
491 " return { run = run, add = add, remove = remove,"
492 " list = list, foreach = foreach,"
493 " restore = restore, save = save}"
496 " sess = ArdourSession ()"
497 " ArdourSession = nil"
500 luabridge::LuaRef *lua_run;
501 luabridge::LuaRef *lua_add;
502 luabridge::LuaRef *lua_del;
503 luabridge::LuaRef *lua_save;
504 luabridge::LuaRef *lua_load;
506 luabridge::LuaRef lua_sess = luabridge::getGlobal (L, "sess");
507 lua.do_command ("sess = nil"); // hide it.
508 lua.do_command ("collectgarbage()");
510 lua_run = new luabridge::LuaRef(lua_sess["run"]);
511 lua_add = new luabridge::LuaRef(lua_sess["add"]);
512 lua_del = new luabridge::LuaRef(lua_sess["remove"]);
513 lua_save = new luabridge::LuaRef(lua_sess["save"]);
514 lua_load = new luabridge::LuaRef(lua_sess["restore"]);
516 lua.do_command ("collectgarbage()");
519 lua.do_command ("function factory (t) return function () local p = t or { } local a = t[1] or 'Nibor' print ('Hello ' .. a) end end");
520 luabridge::LuaRef lua_fact = luabridge::getGlobal (L, "factory");
521 luabridge::LuaRef tbl_arg (luabridge::newTable(L));
522 //tbl_arg[1] = "Robin";
523 (*lua_add)("t2", lua_fact, tbl_arg);
525 lua.do_command ("function factory (t) return function () print ('Boo') end end");
526 luabridge::LuaRef lua_fact = luabridge::getGlobal (L, "factory");
527 (*lua_add)("t2", lua_fact());
530 lua.do_command ("function factory (t) return function () print ('Ahoy') end end");
531 luabridge::LuaRef lua_fact2 = luabridge::getGlobal (L, "factory");
532 (*lua_add)("t1", lua_fact2);
534 luabridge::LuaRef savedstate ((*lua_save)());
535 std::string saved = savedstate.cast<std::string>();
541 } catch (luabridge::LuaException const& e) { printf ("LuaException: %s\n", e.what ()); }
545 for (int i = 0; i < 2; ++i) {
546 lua.do_command ("collectgarbage()");
547 lua.collect_garbage ();
550 } catch (luabridge::LuaException const& e) { printf ("LuaException: %s\n", e.what ()); }
555 add_history("a = Test:A() b = 2 c = 3 d = 'a'");
556 add_history("x = a:get_arg(b) y = a:get_arg2(b, c) z = a:get_args(d) ");
557 add_history("for i,n in ipairs(y) do print (i, n); end");
558 add_history("t = {} t[2] = 7; t[3] = Test:A() t[4] = Test:A() ref:set (t); f = ref:get()");
560 /////////////////////////////////////////////////////////////////////////////
562 while ((line = readline ("> "))) {
563 if (!strcmp (line, "quit")) {
566 if (strlen(line) == 0) {
567 //lua.do_command("collectgarbage();");
570 if (!lua.do_command (line)) {
571 add_history(line); // OK
573 add_history(line); // :)
580 int main (int argc, char **argv)