diff --git a/binding.gyp b/binding.gyp index 252c0c8..47de8e6 100644 --- a/binding.gyp +++ b/binding.gyp @@ -4,6 +4,7 @@ "target_name": "nodelua", "sources": [ "src/utils.cc", + "src/luafunction.cc", "src/luaobject.cc", "src/nodelua.cc" ], diff --git a/example/example.js b/example/example.js index ae032ff..06dac29 100755 --- a/example/example.js +++ b/example/example.js @@ -6,9 +6,11 @@ console.dir(nodelua.INFO); var lua = new nodelua.LuaObject(); -lua.registerFunction('test_func', function(a,b){ +var func = new nodelua.LuaFunction('test_func', function(a,b){ console.dir(a+b); }); +lua.registerFunction(func); + lua.setGlobal("test", 5); diff --git a/src/luafunction.cc b/src/luafunction.cc new file mode 100644 index 0000000..4b828da --- /dev/null +++ b/src/luafunction.cc @@ -0,0 +1,60 @@ +#define BUILDING_NODELUA +#include +#include "luafunction.h" +#include "utils.h" + +using namespace v8; + +LuaFunction::LuaFunction() {}; +LuaFunction::~LuaFunction() {}; + +void LuaFunction::Init(Handle target) { + // Prepare constructor template + Local tpl = FunctionTemplate::New(New); + tpl->SetClassName(String::NewSymbol("LuaFunction")); + tpl->InstanceTemplate()->SetInternalFieldCount(2); + tpl->InstanceTemplate()->SetAccessor(String::New("name"), GetName, SetName); + + Persistent constructor = Persistent::New(tpl->GetFunction()); + target->Set(String::NewSymbol("LuaFunction"), constructor); +} + +LuaFunction* LuaFunction::unwrap(Handle handle){ + return ObjectWrap::Unwrap(handle); +} + +Handle LuaFunction::New(const Arguments& args) { + HandleScope scope; + + if(args.Length() < 2){ + ThrowException(Exception::TypeError(String::New("Must have 2 arguments"))); + return scope.Close(Undefined()); + } + + if(!args[0]->IsString()){ + ThrowException(Exception::TypeError(String::New("Argument 1 must be a string"))); + return scope.Close(Undefined()); + } + + if(!args[1]->IsFunction()){ + ThrowException(Exception::TypeError(String::New("Argument 2 must be a function"))); + return scope.Close(Undefined()); + } + + LuaFunction* obj = new LuaFunction(); + obj->func_name = get_str(args[0]); + obj->func_def_ = Handle::Cast(args[1]); + obj->Wrap(args.This()); + + return args.This(); +} + +Handle LuaFunction::GetName(Local property, const AccessorInfo &info) { + HandleScope scope; + + LuaFunction* obj = ObjectWrap::Unwrap(info.This()); + return scope.Close(String::New(obj->func_name)); +} + +void LuaFunction::SetName(Local property, Local value, const AccessorInfo& info) { +} diff --git a/src/luafunction.h b/src/luafunction.h new file mode 100644 index 0000000..281cdc3 --- /dev/null +++ b/src/luafunction.h @@ -0,0 +1,28 @@ +#ifndef LUAFUNCTION_H +#define LUAFUNCTION_H + +#include + +extern "C"{ +#include +#include +#include +} + +class LuaFunction : public node::ObjectWrap { + public: + static void Init(v8::Handle target); + static LuaFunction* unwrap(v8::Handle handle); + + char *func_name; + v8::Handle func_def_; + private: + LuaFunction(); + ~LuaFunction(); + + static v8::Handle New(const v8::Arguments& args); + static v8::Handle GetName(v8::Local property, const v8::AccessorInfo &info); + static void SetName(v8::Local property, v8::Local value, const v8::AccessorInfo& info); +}; + +#endif diff --git a/src/luaobject.cc b/src/luaobject.cc index 068626a..6a5f90a 100644 --- a/src/luaobject.cc +++ b/src/luaobject.cc @@ -1,14 +1,13 @@ #define BUILDING_NODELUA #include #include "luaobject.h" -#include "utils.h" using namespace v8; LuaObject::LuaObject() {}; LuaObject::~LuaObject() {}; -Local LuaObject::functions = Object::New(); +Persistent functions = Persistent(Object::New()); void LuaObject::Init(Handle target) { // Prepare constructor template @@ -41,10 +40,9 @@ Handle LuaObject::New(const Arguments& args) { HandleScope scope; LuaObject* obj = new LuaObject(); - obj->functions = Object::New(); obj->lua_ = lua_open(); luaL_openlibs(obj->lua_); - lua_register(obj->lua_, "nodelua", obj->LuaFunction); + lua_register(obj->lua_, "nodelua", LuaObject::CallFunction); obj->Wrap(args.This()); return args.This(); @@ -160,20 +158,7 @@ Handle LuaObject::SetGlobal(const Arguments& args) { LuaObject* obj = ObjectWrap::Unwrap(args.This()); - if(args[1]->IsString()){ - String::AsciiValue value(args[1]); - char *value_str = (char *) malloc(value.length() + 1); - strcpy(value_str, *value); - lua_pushstring(obj->lua_, value_str); - }else if(args[1]->IsNumber()){ - int value = args[1]->ToNumber()->Value(); - lua_pushinteger(obj->lua_, value); - }else if(args[1]->IsBoolean()){ - int value = (int)args[1]->ToBoolean()->Value(); - lua_pushboolean(obj->lua_, value); - }else{ - lua_pushnil(obj->lua_); - } + push_value_to_lua(obj->lua_, args[1]); lua_setglobal(obj->lua_, global_name); return scope.Close(Undefined()); @@ -183,28 +168,25 @@ Handle LuaObject::SetGlobal(const Arguments& args) { Handle LuaObject::RegisterFunction(const Arguments& args){ HandleScope scope; - if(args.Length() < 2){ - ThrowException(Exception::TypeError(String::New("Must Have 2 Arguments"))); + if(args.Length() < 1){ + ThrowException(Exception::TypeError(String::New("Must Have 1 Argument"))); return scope.Close(Undefined()); } - if(!args[0]->IsString()){ - ThrowException(Exception::TypeError(String::New("Argument 1 Must Be A String"))); - return scope.Close(Undefined()); - } - - if(!args[1]->IsFunction()){ - ThrowException(Exception::TypeError(String::New("Argument 2 Must Be A Function"))); + if(!args[0]->IsObject()){ + ThrowException(Exception::TypeError(String::New("Argument 1 Must Be An Object"))); return scope.Close(Undefined()); } - LuaObject* obj = ObjectWrap::Unwrap(args.This()); - obj->functions->Set(args[0]->ToString(), args[1]); + Handle handle = Handle::Cast(args[0]); + class LuaFunction* func = LuaFunction::unwrap(handle); + functions->Set(String::New(func->func_name), + func->func_def_); return scope.Close(Undefined()); } -int LuaObject::LuaFunction(lua_State *L){ +int LuaObject::CallFunction(lua_State *L){ int n = lua_gettop(L); if(n < 1){ lua_pushstring(L, "must have at least 1 argument"); @@ -225,8 +207,12 @@ int LuaObject::LuaFunction(lua_State *L){ argv[i-1] = lua_to_value(L, i+1); } - Local func = Local::Cast(LuaObject::functions->Get(func_name)); - func->Call(Context::GetCurrent()->Global(), argc, argv); - - return 0; + Handle ret_val = Undefined(); + if(functions->Has(func_name)){ + Local func = Local::Cast(functions->Get(func_name)); + ret_val = func->Call(Context::GetCurrent()->Global(), argc, argv); + } + + push_value_to_lua(L, ret_val); + return 1; } diff --git a/src/luaobject.h b/src/luaobject.h index b4213a1..a2957e6 100644 --- a/src/luaobject.h +++ b/src/luaobject.h @@ -3,6 +3,9 @@ #include +#include "utils.h" +#include "luafunction.h" + extern "C"{ #include #include @@ -12,8 +15,7 @@ extern "C"{ class LuaObject : public node::ObjectWrap { public: static void Init(v8::Handle target); - static int LuaFunction(lua_State *L); - static v8::Local functions; + static int CallFunction(lua_State *L); private: LuaObject(); diff --git a/src/nodelua.cc b/src/nodelua.cc index 58834c5..5b7b700 100644 --- a/src/nodelua.cc +++ b/src/nodelua.cc @@ -2,6 +2,7 @@ #include #include "luaobject.h" +#include "luafunction.h" extern "C"{ #include @@ -43,6 +44,7 @@ void init_gc_constants(Handle target){ void init(Handle target) { LuaObject::Init(target); + LuaFunction::Init(target); init_gc_constants(target); init_status_constants(target); init_info_constants(target); diff --git a/src/utils.cc b/src/utils.cc index 27c9e4b..675e268 100644 --- a/src/utils.cc +++ b/src/utils.cc @@ -29,3 +29,17 @@ v8::Local lua_to_value(lua_State* L, int i){ break; } } + +void push_value_to_lua(lua_State* L, v8::Handle value){ + if(value->IsString()){ + lua_pushstring(L, get_str(v8::Local::New(value))); + }else if(value->IsNumber()){ + int i_value = value->ToNumber()->Value(); + lua_pushinteger(L, i_value); + }else if(value->IsBoolean()){ + int b_value = (int)value->ToBoolean()->Value(); + lua_pushboolean(L, b_value); + }else{ + lua_pushnil(L); + } +} diff --git a/src/utils.h b/src/utils.h index 2637a3a..49f8218 100644 --- a/src/utils.h +++ b/src/utils.h @@ -11,5 +11,5 @@ extern "C"{ char * get_str(v8::Local val); v8::Local lua_to_value(lua_State* L, int); - +void push_value_to_lua(lua_State* L, v8::Handle value); #endif