#define BUILDING_NODELUA #include #include #include "luaobject.h" using namespace v8; LuaObject::LuaObject() {}; LuaObject::~LuaObject() {}; std::map > functions; void LuaObject::Init(Handle target) { // Prepare constructor template Local tpl = FunctionTemplate::New(New); tpl->SetClassName(String::NewSymbol("LuaObject")); tpl->InstanceTemplate()->SetInternalFieldCount(1); // Prototype tpl->PrototypeTemplate()->Set(String::NewSymbol("doFile"), FunctionTemplate::New(DoFile)->GetFunction()); tpl->PrototypeTemplate()->Set(String::NewSymbol("doString"), FunctionTemplate::New(DoString)->GetFunction()); tpl->PrototypeTemplate()->Set(String::NewSymbol("getGlobal"), FunctionTemplate::New(GetGlobal)->GetFunction()); tpl->PrototypeTemplate()->Set(String::NewSymbol("setGlobal"), FunctionTemplate::New(SetGlobal)->GetFunction()); tpl->PrototypeTemplate()->Set(String::NewSymbol("registerFunction"), FunctionTemplate::New(RegisterFunction)->GetFunction()); tpl->PrototypeTemplate()->Set(String::NewSymbol("status"), FunctionTemplate::New(Status)->GetFunction()); tpl->PrototypeTemplate()->Set(String::NewSymbol("collectGarbage"), FunctionTemplate::New(CollectGarbage)->GetFunction()); tpl->PrototypeTemplate()->Set(String::NewSymbol("close"), FunctionTemplate::New(Close)->GetFunction()); tpl->PrototypeTemplate()->Set(String::NewSymbol("push"), FunctionTemplate::New(Push)->GetFunction()); tpl->PrototypeTemplate()->Set(String::NewSymbol("pop"), FunctionTemplate::New(Pop)->GetFunction()); tpl->PrototypeTemplate()->Set(String::NewSymbol("getTop"), FunctionTemplate::New(GetTop)->GetFunction()); tpl->PrototypeTemplate()->Set(String::NewSymbol("setTop"), FunctionTemplate::New(SetTop)->GetFunction()); tpl->PrototypeTemplate()->Set(String::NewSymbol("replace"), FunctionTemplate::New(Replace)->GetFunction()); Persistent constructor = Persistent::New(tpl->GetFunction()); target->Set(String::NewSymbol("LuaObject"), constructor); } Handle LuaObject::New(const Arguments& args) { HandleScope scope; LuaObject* obj = new LuaObject(); obj->lua_ = lua_open(); luaL_openlibs(obj->lua_); lua_register(obj->lua_, "nodelua", LuaObject::CallFunction); obj->Wrap(args.This()); return args.This(); } Handle LuaObject::Close(const Arguments& args){ HandleScope scope; LuaObject* obj = ObjectWrap::Unwrap(args.This()); lua_close(obj->lua_); return scope.Close(Undefined()); } Handle LuaObject::Status(const Arguments& args){ HandleScope scope; LuaObject* obj = ObjectWrap::Unwrap(args.This()); int status = lua_status(obj->lua_); return scope.Close(Number::New(status)); } Handle LuaObject::CollectGarbage(const Arguments& args){ HandleScope scope; if(args.Length() < 1){ ThrowException(Exception::TypeError(String::New("Wrong number of arguments"))); return scope.Close(Undefined()); } if(!args[0]->IsNumber()){ ThrowException(Exception::TypeError(String::New("Argument 1 must be a number, try nodelua.GC"))); return scope.Close(Undefined()); } LuaObject* obj = ObjectWrap::Unwrap(args.This()); int type = (int)args[0]->ToNumber()->Value(); int gc = lua_gc(obj->lua_, type, 0); return scope.Close(Number::New(gc)); } Handle LuaObject::DoFile(const Arguments& args) { HandleScope scope; if(args.Length() < 1){ ThrowException(Exception::TypeError(String::New("Wrong number of arguments"))); return scope.Close(Undefined()); } char *file_name = get_str(args[0]); LuaObject* obj = ObjectWrap::Unwrap(args.This()); if(luaL_dofile(obj->lua_, file_name)){ char buf[1000]; sprintf(buf, "Execution Of File %s Has Failed:\n%s\n", file_name, lua_tostring(obj->lua_, -1)); ThrowException(Exception::TypeError(String::New(buf))); return scope.Close(Undefined()); } return scope.Close(Undefined()); } Handle LuaObject::DoString(const Arguments& args) { HandleScope scope; if(args.Length() < 1){ ThrowException(Exception::TypeError(String::New("Wrong number of arguments"))); return scope.Close(Undefined()); } char *lua_code = get_str(args[0]); LuaObject* obj = ObjectWrap::Unwrap(args.This()); if(luaL_dostring(obj->lua_, lua_code)){ char buf[1000]; sprintf(buf, "Execution Of Lua Code Has Failed:\n%s\n", lua_tostring(obj->lua_, -1)); ThrowException(Exception::TypeError(String::New(buf))); return scope.Close(Undefined()); } return scope.Close(Undefined()); } Handle LuaObject::GetGlobal(const Arguments& args) { HandleScope scope; if(args.Length() < 1){ ThrowException(Exception::TypeError(String::New("Wrong number of arguments"))); return scope.Close(Undefined()); } char *global_name = get_str(args[0]); LuaObject* obj = ObjectWrap::Unwrap(args.This()); lua_getglobal(obj->lua_, global_name); Local val = lua_to_value(obj->lua_, -1); return scope.Close(val); } Handle LuaObject::SetGlobal(const Arguments& args) { HandleScope scope; if(args.Length() < 2){ ThrowException(Exception::TypeError(String::New("Wrong number of arguments"))); return scope.Close(Undefined()); } char *global_name = get_str(args[0]); LuaObject* obj = ObjectWrap::Unwrap(args.This()); push_value_to_lua(obj->lua_, args[1]); lua_setglobal(obj->lua_, global_name); return scope.Close(Undefined()); } Handle LuaObject::Push(const Arguments& args) { HandleScope scope; if(args.Length() < 1){ ThrowException(Exception::TypeError(String::New("Wrong number of arguments"))); return scope.Close(Undefined()); } LuaObject* obj = ObjectWrap::Unwrap(args.This()); push_value_to_lua(obj->lua_, args[0]); return scope.Close(Undefined()); } Handle LuaObject::Pop(const Arguments& args) { HandleScope scope; int pop_n = 1; if(args.Length() > 0 && args[0]->IsNumber()){ pop_n = (int)args[0]->ToNumber()->Value(); } LuaObject* obj = ObjectWrap::Unwrap(args.This()); lua_pop(obj->lua_, pop_n); return scope.Close(Undefined()); } Handle LuaObject::GetTop(const Arguments& args) { HandleScope scope; LuaObject* obj = ObjectWrap::Unwrap(args.This()); int n = lua_gettop(obj->lua_); return scope.Close(Number::New(n)); } Handle LuaObject::SetTop(const Arguments& args) { HandleScope scope; int set_n = 0; if(args.Length() > 0 && args[0]->IsNumber()){ set_n = (int)args[0]->ToNumber()->Value(); } LuaObject* obj = ObjectWrap::Unwrap(args.This()); lua_settop(obj->lua_, set_n); return scope.Close(Undefined()); } Handle LuaObject::Replace(const Arguments& args) { HandleScope scope; if(args.Length() < 1){ ThrowException(Exception::TypeError(String::New("Must Have 1 Argument"))); return scope.Close(Undefined()); } if(!args[0]->IsNumber()){ ThrowException(Exception::TypeError(String::New("Argument 1 Must Be A Number"))); return scope.Close(Undefined()); } int index = (int)args[0]->ToNumber()->Value(); LuaObject* obj = ObjectWrap::Unwrap(args.This()); lua_replace(obj->lua_, index); return scope.Close(Undefined()); } Handle LuaObject::RegisterFunction(const Arguments& args){ HandleScope scope; if(args.Length() < 1){ ThrowException(Exception::TypeError(String::New("Must Have 1 Argument"))); return scope.Close(Undefined()); } if(!args[0]->IsObject()){ ThrowException(Exception::TypeError(String::New("Argument 1 Must Be An Object"))); return scope.Close(Undefined()); } Handle handle = Handle::Cast(args[0]); class LuaFunction* func = LuaFunction::unwrap(handle); functions[func->func_name] = func->func_def_; return scope.Close(Undefined()); } int LuaObject::CallFunction(lua_State *L){ int n = lua_gettop(L); if(n < 1){ lua_pushstring(L, "must have at least 1 argument"); lua_error(L); } if (!lua_isstring(L, 1)) { lua_pushstring(L, "argument 1 must be a string"); lua_error(L); } char * func_name = (char *)lua_tostring(L, 1); const unsigned argc = n - 1; Local* argv = new Local[argc]; int i; for(i = 1; i <= n; ++i){ argv[i-1] = lua_to_value(L, i+1); } Handle ret_val = Undefined(); std::map >::iterator iter; for(iter = functions.begin(); iter != functions.end(); iter++){ if(strcmp(iter->first, func_name) == 0){ Persistent func = iter->second; ret_val = func->Call(Context::GetCurrent()->Global(), argc, argv); break; } } push_value_to_lua(L, ret_val); return 1; }