1 #include "common_bind.hpp"
3 #define LQT_FIXEDINDEX(i) (i<0?(1+lua_gettop(L)+i):i)
7 # define SEE_STACK(L, j) for (int j=1;j<=lua_gettop(L);j++) { qDebug() << j << '=' << luaL_typename(L, j) << '@' << lua_topointer (L, j); }
12 // - add a metatable for void* which always results in nil and possibly
13 // accounts for reassigning the userdata to the right metatable.
14 // - proper descending down the dependency tree for indexing, and proper
15 // handling of missing binds
20 //using namespace std;
22 void lqtL_setvoidmetatable (lua_State
*L
, int i
, const char *t
= 0) {
23 i
= LQT_FIXEDINDEX(i
);
24 if (luaL_newmetatable(L
, "void*")) {
26 lua_setfield(L
, -2, "__index");
27 lua_pushstring(L
, "void*");
28 lua_setfield(L
, -2, "__qtype");
30 lua_setmetatable(L
, i
);
34 lua_setfield(L
, -2, "__unknown_type");
39 void lqtL_getpointers (lua_State
*L
) {
40 lua_getfield(L
, LUA_REGISTRYINDEX
, LQT_POINTERS
);
41 if (!lua_istable(L
, -1)) {
42 //cout << "Registry Pointers created" << endl;
46 lua_pushstring(L
, "kv");
47 lua_setfield(L
, -2, "__mode");
48 lua_setmetatable(L
, -2);
50 lua_setfield(L
, LUA_REGISTRYINDEX
, LQT_POINTERS
);
55 int lqtL_reusepointer (lua_State
*L
, const void *p
, const char *t
) {
57 lua_pushlightuserdata(L
, const_cast<void*>(p
));
59 if (lqtL_testudata(L
, -1, t
) && (p
==*(const void**)lua_touserdata(L
, -1))) {
62 //qDebug() << "reused" << p << "in" << lua_touserdata(L, -1) << t;
63 //lua_getmetatable(L, -1);luaL_getmetatable(L, t);
64 //qDebug() << "meta" << lua_topointer(L, -2) << "type" << lua_topointer(L, -1);
72 void lqtL_pushpointer (lua_State
*L
, const void *obj
, const char *t
) {
73 const void **objp
= (const void**)lua_newuserdata(L
, sizeof(const void *));
75 lua_getfield(L
, LUA_REGISTRYINDEX
, t
);
76 if (lua_istable(L
, -1)) {
77 lua_setmetatable(L
, -2);
81 //cout << "NO metatable given" << endl;
82 // TODO: add a fallback?
84 lqtL_setvoidmetatable(L
, -1, t
);
87 //cout << "pushed " << objp << ' ' << obj << endl;
90 void lqtL_setpointer (lua_State
*L
, int i
, const void *obj
) {
91 int index
= i
<0?(1+lua_gettop(L
)+i
):i
;
92 //cout << lua_gettop(L) << ' ' << i << ' ' << index << endl;
94 lua_pushlightuserdata(L
, const_cast<void *>(obj
));
95 lua_pushvalue(L
, index
);
100 void lqtL_unsetpointer (lua_State
*L
, const void *obj
) {
102 lua_pushlightuserdata(L
, const_cast<void *>(obj
));
109 // TODO: don't need, it's debug
110 void * lqtL_topointer (lua_State
*L
, int i
) {
112 ret
= lua_touserdata(L
, i
);
113 ret
= (ret
==0)?0:*static_cast<void**>(ret
);
117 void lqtL_unmanageudata (lua_State
*L
, int i
) {
118 if (!lua_isuserdata(L
, i
)) return;
120 if (lua_istable(L
, -1)) {
122 lua_setfield(L
, -2, "__gc");
127 void lqtL_manageudata (lua_State
*L
, int index
) {
128 //luaL_checkstack(L, 20, "");
129 index
= LQT_FIXEDINDEX(index
);
130 if (!lua_isuserdata(L
, index
)) return;
131 lua_getfield(L
, index
, "delete");
132 if (!lua_isfunction(L
, -1)) {
136 lua_getfenv(L
, index
);
137 if (!lua_istable(L
, -1)) {
141 lua_pushvalue(L
, -1);
142 lua_setfenv(L
, index
);
145 lua_setfield(L
, -2, "__gc");
149 void lqtL_pushudata (lua_State
*L
, const void *obj
, const char *t
) {
150 // TODO: make the udata unique
151 //cout << endl << "pushing udata " << obj << " with type " << t << endl;
153 lua_checkstack(L
, 5);
155 if (lqtL_reusepointer(L
, obj
, t
)) {
156 //cout << obj << " reused " << t << endl;
159 //cout << obj << " NOT reused " << t << endl;
162 lua_pushlightuserdata(L
, const_cast<void *>(obj
));
165 //cout << lua_gettop(L) << endl;
166 lua_getglobal(L
, "print");
167 if (lua_getmetatable(L
, -2)) {
168 //cout << "metatable "; // << lua_tostring(L, -1) << endl << endl;
171 //cout << "no metatable" << endl;
174 //cout << lua_gettop(L) << endl;
175 lua_getglobal(L
, "print");
176 lua_getfield(L
, LUA_REGISTRYINDEX
, t
);
177 //cout << "registry "; // << lua_tostring(L, -1) << endl; lua_pop(L, 1);
180 //cout << lua_gettop(L) << endl;
181 if (lua_getmetatable(L
, -1)) {
182 lua_getfield(L
, LUA_REGISTRYINDEX
, t
);
183 //cout << (bool)lua_equal(L, -1, -2) << endl;
184 lua_getglobal(L
, "print");
188 //cout << "no metatable" << endl;
192 if (lqtL_testudata(L
, -1, t
)) {
193 //cout << obj << " reused" << endl;
197 //cout << luaL_typename(L, -1) << " testudata failed " << lua_touserdata(L, -1) << ' ' << lqtL_topointer(L, -1) << endl;
203 lqtL_pushpointer(L
, obj
, t
);
205 const void **objp
= (const void**)lua_newuserdata(L
, sizeof(const void *));
207 lua_getfield(L
, LUA_REGISTRYINDEX
, t
);
208 if (lua_istable(L
, -1)) {
209 lua_setmetatable(L
, -2);
211 //cout << "NO metatable given" << endl;
213 // TODO: add a fallback?
216 //cout << "pushed " << objp << ' ' << obj << endl;
218 //cout << lua_gettop(L) << endl;
220 lqtL_setpointer(L
, -1, obj
);
222 lua_getfield(L
, LUA_REGISTRYINDEX
, LQT_POINTERS
);
223 lua_pushlightuserdata(L
, const_cast<void *>(obj
));
224 lua_pushvalue(L
, -3);
228 //cout << lua_gettop(L) << endl;
230 void lqtL_passudata (lua_State
*L
, const void *obj
, const char *t
) {
231 //cout << "passing: " << obj << " " << t << endl;
232 lqtL_pushudata(L
, obj
, t
);
233 lqtL_manageudata(L
, -1);
237 int lqtL_derivesfrom (lua_State
*L
, int i
, const char *t
) {
239 int oldtop
= lua_gettop(L
);
240 i
= LQT_FIXEDINDEX(i
);
242 if (!lua_istable(L
, i
)) {
246 luaL_checkstack(L
, 1, "cannot grow stack for checking object type");
248 //qDebug() << "given a table" << lua_topointer(L, i);
249 lua_getfield(L
, LUA_REGISTRYINDEX
, t
);
250 //qDebug() << "table" << t << lua_topointer(L, -1);
251 ret
= lua_equal(L
, i
, -1);
252 //qDebug() << "same as" << t << "?" << (bool)ret;
255 lua_settop(L, oldtop);
262 luaL_checkstack(L
, 13, "cannot grow stack for checking object type"); // FIXME: is it enough?
263 lua_getfield(L
, i
, "__base");
265 if (!lua_istable(L
, -1)) {
269 lua_getfield(L
, -1, t
);
270 ret
= lua_isnil(L
, -1)?0:1;
271 // DANGER: order of control expression is important
272 while ((ret
== 0) && (lua_next(L
, -2) != 0)) {
273 if (!lua_istable(L
, -1)) {
275 lua_pushvalue(L
, -1);
276 lua_gettable(L
, LUA_REGISTRYINDEX
);
277 if (lua_istable(L
, -1)) {
278 lua_pushvalue(L
, -2);
279 lua_pushvalue(L
, -2);
283 if (lua_istable(L
, -1)) {
284 ret
= lqtL_derivesfrom(L
, -1, t
);
291 lua_settop(L
, oldtop
);
296 bool lqtL_testudata (lua_State
*L
, int i
, const char *t
) {
297 //qDebug() << "================ testudata" << t;
298 //luaL_checkstack(L, 99, "");
299 i
= LQT_FIXEDINDEX(i
);
301 if (lua_getmetatable(L
, i
)) {
302 //SEE_STACK(L, pippo);
303 //SEE_STACK(L, pippo);
305 lua_getfield(L
, LUA_REGISTRYINDEX
, "QEvent*");
306 if (0 && lua_istable(L
, -1)) {
307 lua_getfield(L
, -1, "__qtype");
308 //SEE_STACK(L, pippo);
313 ret
= (bool) lqtL_derivesfrom(L
, -1, t
);
315 //qDebug() << "derives?" << ret;
316 if (!ret
&& lqtL_derivesfrom(L
, -1, "void*")) {
317 //cout << "checking for a generic void* pointer" << endl;
319 luaL_checkstack(L
, 3, "cannot check void* real type");
321 lua_getfield(L
, -1, "__unknown_type");
322 //TODO: assign dynamically?
323 lua_pushstring(L
, t
);
324 ret
= (bool)lua_equal(L
, -1, -2);
327 // FIXME: deleting makes QMetaObjects not work
333 //cout << t << (ret?"":" NOT") <<" found" << endl;
337 int oldtop = lua_gettop(L);
338 lua_getfield(L, LUA_REGISTRYINDEX, t);
339 if (lua_getmetatable(L, i)) {
340 ret = (bool)lua_equal(L, -1, -2);
343 ret = lqTL_derivesfrom(L, -1, t);
346 lua_settop(L, oldtop);
352 int lqtL_pushtype (lua_State
*L
, int i
) {
353 int type
= lua_type(L
, i
);
354 if (type
!= LUA_TUSERDATA
) {
355 lua_pushstring(L
, lua_typename(L
, type
));
357 lua_getfield(L
, i
, "__qtype");
358 if (!lua_isstring(L
, -1)) {
360 lua_pushstring(L
, "<unknown>");
366 void * lqtL_checkudata (lua_State
*L
, int i
, const char *t
) {
367 if (lqtL_testudata(L
, i
, t
)) {
368 return lua_touserdata(L
, i
);
370 lua_pushstring(L
, "Fatal error: userdata type mismatch. requested ");
371 lua_pushstring(L
, t
);
372 lua_pushstring(L
, " found ");
380 void * lqtL_toudata (lua_State
*L
, int i
, const char *t
) {
382 if (lqtL_testudata(L
, i
, t
)) {
383 ret
= *static_cast<void**>(lua_touserdata(L
, i
));
388 void lqtL_pushenum (lua_State
*L
, int v
, const char *e
) {
389 lua_getfield(L
, LUA_REGISTRYINDEX
, LQT_ENUMS
);
390 if (lua_istable(L
, -1)) {
391 //qDebug() << "LQT_ENUMS is a table";
392 lua_getfield(L
, -1, e
);
395 //qDebug() << "LQT_ENUMS is NOT a table";
397 lua_pushinteger(L
, v
);
398 if (lua_istable(L
, -2)) {
399 //qDebug() << "getting translation";
402 //qDebug() << "no translation table for" << e;
406 bool lqtL_isenum (lua_State
*L
, int i
, const char *e
) {
408 if (lua_type(L
, i
)==LUA_TNUMBER
) {
409 ret
= (lua_tointeger(L
, i
)==lua_tonumber(L
, i
));
410 } else if (lua_type(L
, i
)==LUA_TSTRING
) {
411 lua_getfield(L
, LUA_REGISTRYINDEX
, LQT_ENUMS
);
412 if (lua_istable(L
, -1)) {
413 lua_getfield(L
, -1, e
);
417 if (lua_istable(L
, -2)) {
420 if (lua_type(L
, -1)==LUA_TNUMBER
) {
421 ret
= (lua_tointeger(L
, -1)==lua_tonumber(L
, -1));
427 int lqtL_toenum (lua_State
*L
, int i
, const char *e
) {
429 if (lua_type(L
, i
)==LUA_TNUMBER
) {
430 ret
= lua_tointeger(L
, i
);
431 } else if (lua_type(L
, i
)==LUA_TSTRING
) {
432 lua_getfield(L
, LUA_REGISTRYINDEX
, LQT_ENUMS
);
433 if (lua_istable(L
, -1)) {
434 lua_getfield(L
, -1, e
);
438 if (lua_istable(L
, -2)) {
441 if (lua_type(L
, -1)==LUA_TNUMBER
) {
442 ret
= lua_tointeger(L
, -1);
449 int lqtL_baseindex (lua_State
*L
, int index
, int key
) {
451 int oldtop
= lua_gettop(L
);
452 index
= LQT_FIXEDINDEX(index
);
453 key
= LQT_FIXEDINDEX(key
);
455 if (!lua_istable(L
, index
)) {
459 luaL_checkstack(L
, 1, "cannot grow stack for retrieving member");
461 lua_pushvalue(L
, key
);
462 lua_gettable(L
, index
);
464 if (!lua_isnil(L
, -1)) {
467 luaL_checkstack(L
, 7, "cannot grow stack for retrieving member"); // FIXME: is it enough?
468 lua_getfield(L
, index
, "__base");
470 if (!lua_istable(L
, -1)) {
475 // DANGER: order of control expression is important
476 while ((ret
== 0) && (lua_next(L
, -2) != 0)) {
477 if (!lua_istable(L
, -1)) {
479 lua_pushvalue(L
, -1);
480 lua_gettable(L
, LUA_REGISTRYINDEX
);
481 if (lua_istable(L
, -1)) {
482 lua_pushvalue(L
, -2);
483 lua_pushvalue(L
, -2);
487 if (lua_istable(L
, -1)) {
488 ret
= lqtL_baseindex(L
, -1, key
);
498 lua_insert(L
, oldtop
+1);
500 lua_settop(L
, oldtop
+ret
);
505 int lqtL_index (lua_State
*L
) {
507 luaL_checkstack(L
, 1, "cannot grow stack for retrieving member");
508 if (!lua_getmetatable(L
, 1)) {
512 return lqtL_baseindex(L
, 3, 2);
514 luaL_checkstack(L, 2, "cannot grow stack for retrieving member");
515 lua_getmetatable(L, 1);
516 if (lua_istable(L, -1)) {
527 int lqtL_newindex (lua_State
*L
) {
528 if (!lua_getmetatable(L
, 1)) {
531 if (lua_istable(L
, -1)) {
540 int lqtL_gc (lua_State
*L
) {
541 if (!lua_isuserdata(L
, 1)) return 0;
544 if (lua_istable(L
, -1)) {
545 lua_getfield(L
, -1, "__gc");
546 if (lua_isfunction(L
, -1)) {
547 //cout << "found fenv gc " << lua_topointer(L, -1) << endl;
551 //cout << "NOT found fenv gc" << endl;
557 // FIXME: this is useless, isn't it?
558 void **p
= static_cast<void**>(lua_touserdata(L
, 1));