summaryrefslogtreecommitdiff
path: root/lib/BLua.cc
diff options
context:
space:
mode:
authorpixel <pixel>2003-11-14 17:19:55 +0000
committerpixel <pixel>2003-11-14 17:19:55 +0000
commit7741890b069ad9bad9748730e08f39d75a14c16a (patch)
treefaca031e567048c8d2bbdf1aa03ef358be2c0cb6 /lib/BLua.cc
parentea55afb084188cb4dca285545ab84cf647b504c2 (diff)
Started writing LUA bindings... Handles are done. (almost)
Diffstat (limited to 'lib/BLua.cc')
-rw-r--r--lib/BLua.cc298
1 files changed, 287 insertions, 11 deletions
diff --git a/lib/BLua.cc b/lib/BLua.cc
index 286857e..18789f7 100644
--- a/lib/BLua.cc
+++ b/lib/BLua.cc
@@ -1,27 +1,38 @@
+#include <lualib.h>
#include "BLua.h"
-#ifndef LUAL_BUFFERSIZE
-#define LUAL_BUFFERSIZE BUFSIZ
+#ifndef BUFFERSIZE
+#define BUFFERSIZE 2048
#endif
+typedef GeneralException LuaException;
+
class LuaStatics : public Base {
public:
static const char * getF(lua_State *, void *, size_t *);
+ static int luapanic(lua_State *) throw(GeneralException);
+ static int destructor(lua_State *);
};
std::map<lua_State *, Lua *> Lua::lualist;
+int LuaStatics::luapanic(lua_State * L) throw (GeneralException) {
+ Lua::find(L)->showerror();
+ throw LuaException("Error running Lua code, bailing out.");
+}
+
Lua::Lua() : L(lua_open()) {
- // error setting ? **TODO**
+ lua_atpanic(L, LuaStatics::luapanic);
lualist[L] = this;
}
Lua::Lua(lua_State * _L) : L(_L) {
- // error setting ? **TODO**
+ lua_atpanic(L, LuaStatics::luapanic);
lualist[L] = this;
}
Lua::~Lua() {
+ lua_setgcthreshold(L, 0);
lua_close(L);
}
@@ -29,11 +40,58 @@ Lua::Lua(const Lua & l) throw (GeneralException) {
throw GeneralException("Error: can't duplicate a Lua object.");
}
+void Lua::open_base() {
+ luaopen_base(L);
+ lua_pop(L, 1);
+}
+
+void Lua::open_table() {
+ luaopen_table(L);
+ lua_pop(L, 1);
+}
+
+void Lua::open_io() {
+ luaopen_io(L);
+ lua_pop(L, 1);
+}
+
+void Lua::open_string() {
+ luaopen_string(L);
+ lua_pop(L, 1);
+}
+
+void Lua::open_math() {
+ luaopen_math(L);
+ lua_pop(L, 1);
+}
+
+void Lua::open_debug() {
+ luaopen_debug(L);
+ lua_pop(L, 1);
+}
+
+void Lua::declarefunc(const String & name, lua_CFunction f, int i) {
+ lua_pushstring(L, name.to_charp());
+ lua_pushcfunction(L, f);
+ lua_settable(L, i);
+}
+
+void Lua::call(const String & f, int i, int nargs, int nresults) {
+ lua_pushstring(L, f.to_charp());
+ lua_gettable(L, i);
+ lua_insert(L, -1 - nargs - nresults);
+ lua_call(L, nargs, nresults);
+}
+
+void Lua::call(int nargs, int nresults) {
+ lua_call(L, nargs, nresults);
+}
+
void Lua::push() {
lua_pushnil(L);
}
-void Lua::push(double n) {
+void Lua::push(lua_Number n) {
lua_pushnumber(L, n);
}
@@ -53,16 +111,111 @@ void Lua::push(lua_CFunction f, int n) {
lua_pushcclosure(L, f, n);
}
+void Lua::pop(int n) {
+ lua_pop(L, n);
+}
+
+void Lua::newtable() {
+ lua_newtable(L);
+}
+
+void Lua::settable(int i) {
+ lua_settable(L, i);
+}
+
+void Lua::gettable(int i) {
+ lua_gettable(L, i);
+}
+
+int Lua::gettop() {
+ return lua_gettop(L);
+}
+
+void Lua::error(const String & msg) {
+ push(msg);
+ lua_error(L);
+}
+
+int Lua::type(int i) {
+ return lua_type(L, i);
+}
+
+bool Lua::isnil(int i) {
+ return lua_isnil(L, i);
+}
+
+bool Lua::isboolean(int i) {
+ return lua_isboolean(L, i);
+}
+
+bool Lua::isnumber(int i) {
+ return lua_isnumber(L, i);
+}
+
+bool Lua::isstring(int i) {
+ return lua_isstring(L, i);
+}
+
+bool Lua::istable(int i) {
+ return lua_istable(L, i);
+}
+
+bool Lua::isfunction(int i) {
+ return lua_isfunction(L, i);
+}
+
+bool Lua::iscfunction(int i) {
+ return lua_iscfunction(L, i);
+}
+
+bool Lua::isuserdata(int i) {
+ return lua_isuserdata(L, i);
+}
+
+bool Lua::islightuserdata(int i) {
+ return lua_islightuserdata(L, i);
+}
+ bool toboolean(int = -1);
+ lua_Number tonumber(int = -1);
+ String tostring(int = -1);
+ lua_CFunction tocfunction(int = -1);
+ void * touserdata(int = -1);
+ Lua * tothread(int = -1);
+
+bool Lua::toboolean(int i) {
+ return lua_toboolean(L, i);
+}
+
+lua_Number Lua::tonumber(int i) {
+ return lua_tonumber(L, i);
+}
+
+String Lua::tostring(int i) {
+ return String(lua_tostring(L, i));
+}
+
+lua_CFunction Lua::tocfunction(int i) {
+ return lua_tocfunction(L, i);
+}
+
+void * Lua::touserdata(int i) {
+ return lua_touserdata(L, i);
+}
+
+Lua * Lua::tothread(int i) {
+ return find(lua_tothread(L, i));
+}
+
struct LoadF {
Handle * f;
- char buff[LUAL_BUFFERSIZE];
+ char buff[BUFFERSIZE];
};
const char * LuaStatics::getF(lua_State * L, void * ud, size_t * size) {
LoadF *lf = (LoadF *)ud;
(void)L;
- *size = lf->f->read(lf->buff, LUAL_BUFFERSIZE);
+ *size = lf->f->read(lf->buff, BUFFERSIZE);
return (*size > 0) ? lf->buff : NULL;
}
@@ -75,15 +228,138 @@ void Lua::load(Handle * h) throw (GeneralException) {
status = lua_load(L, LuaStatics::getF, &lf, h->GetName().to_charp());
if (status) {
- // displaying error **TODO**
- throw GeneralException("Error loading lua chunk `" + h->GetName() + "'");
+ showerror();
+ throw LuaException("Error loading lua chunk from Handle `" + h->GetName() + "'");
}
+
+ call();
}
Lua * Lua::thread() {
return new Lua(lua_newthread(L));
}
-Lua * Lua::find(lua_State * _L) {
- return lualist.find(_L)->second;
+Lua * Lua::find(lua_State * _L) throw (GeneralException) {
+ std::map<lua_State *, Lua *>::iterator i;
+
+ if ((i = lualist.find(_L)) == lualist.end()) {
+ throw GeneralException("Unable to find the Lua object for this context");
+ }
+
+ return i->second;
+}
+
+void Lua::showerror() {
+ int n = lua_gettop(L);
+ int i;
+ String t;
+
+ printm(M_ERROR, "Lua object: Got an LUA error\n");
+ printm(M_ERROR, "Inspecting LUA stack\n");
+
+ if (n == 0) {
+ printm(M_ERROR, "Stack empty\n");
+ return;
+ }
+
+ for (i = 1; i <= n; i++) {
+ switch(lua_type(L, i)) {
+ case LUA_TNONE:
+ t = "Invalid";
+ break;
+ case LUA_TNIL:
+ t = "(Nil)";
+ break;
+ case LUA_TNUMBER:
+ t.set("(Number) %f", lua_tonumber(L, i));
+ break;
+ case LUA_TBOOLEAN:
+ t.set("(Bool) %s", lua_toboolean(L, i) ? "true" : "false");
+ break;
+ case LUA_TSTRING:
+ t.set("(String) %s", lua_tostring(L, i));
+ break;
+ case LUA_TTABLE:
+ t = "(Table)";
+ break;
+ case LUA_TFUNCTION:
+ t = "(Function)";
+ break;
+ default:
+ t = "Unknown";
+ }
+
+ printm(M_ERROR, String(i) + ": " + t + "\n");
+ }
+}
+
+int Lua::getmetatable(int i) {
+ return lua_getmetatable(L, i);
+}
+
+int Lua::setmetatable(int i) {
+ return lua_setmetatable(L, i);
+}
+
+void LuaObject::push(Lua * L) throw (GeneralException) {
+ if (pushed && wantdestruct) {
+ throw GeneralException("Error: object is owned by the LUA script and can not be pushed.");
+ }
+ L->newtable();
+ pushmembers(L);
+ pushed = true;
+}
+
+void LuaObject::pushme(Lua * L, void * o) {
+ L->push("__obj");
+ L->push(o);
+ L->settable();
+}
+
+void * LuaObject::getme(Lua * L, int i) throw (GeneralException) {
+ void * r;
+
+ L->push("__obj");
+ L->gettable(i);
+ if (!(r = L->touserdata())) {
+ throw GeneralException("Lua object already destroyed");
+ }
+ L->pop();
+
+ return r;
+}
+
+void LuaObject::pushit(Lua * L, const String & s, lua_CFunction f) {
+ L->push(s);
+ L->push(f);
+ L->settable();
+}
+
+int LuaStatics::destructor(lua_State * _L) {
+ Lua * L = Lua::find(_L);
+ Base * b = (Base *) LuaObject::getme(L);
+ delete b;
+ L->push("__obj");
+ L->push((void *) 0);
+ L->settable();
+ printm(M_INFO, "Destructing an object from LUA\n");
+ return 0;
+}
+
+
+void LuaObject::pushdestruct(Lua * L) throw (GeneralException) {
+ if (pushed) {
+ throw GeneralException("Error: can't push destructor, object already pushed");
+ }
+ push(L);
+ if (!L->getmetatable(1)) {
+ L->newtable();
+ }
+ L->push("__gc");
+ L->push(LuaStatics::destructor);
+ L->settable();
+ L->setmetatable(1);
+ pushit(L, "destroy", LuaStatics::destructor);
+
+ wantdestruct = true;
}