Browse Source

added pop, push, replace, gettop, settop LuaObject functions, setup LuaObject to use LuaFunction objects, version bump and updated readme

v0.1.x
Brett Langdon 13 years ago
parent
commit
6e5023efef
13 changed files with 230 additions and 58 deletions
  1. +62
    -16
      README.md
  2. +5
    -0
      example/config/config.lua
  3. +17
    -0
      example/config/index.js
  4. +10
    -0
      example/constants/index.js
  5. +0
    -26
      example/example.js
  6. +22
    -0
      example/functions/index.js
  7. +11
    -0
      example/simple/index.js
  8. +0
    -6
      example/test.lua
  9. +1
    -1
      package.json
  10. +1
    -1
      src/luafunction.cc
  11. +1
    -1
      src/luafunction.h
  12. +95
    -7
      src/luaobject.cc
  13. +5
    -0
      src/luaobject.h

+ 62
- 16
README.md View File

@ -18,7 +18,7 @@ var nodelua = require('nodelua');
## API
### NodeLua
The `NodeLua` module itself only contains a single object `LuaObject` used to initialize a single `lua_State` as well as some constants.
The `NodeLua` module itself contains the objects `LuaObject`, `LuaFunction`, as well as some constants.
```javascript
var lua = new nodelua.LuaObject()
```
@ -55,6 +55,25 @@ var lua = new nodelua.LuaObject()
* `COPYRIGHT`
* `AUTHORS`
### LuaFunction
The `LuaFunction` is used to initialize a javascript function for use by lua.
One caveat to using `LuaFunction`s and multiple `LuaObject`s is that `LuaFunction`s regardless of which `LuaObject`
they are registered with are visable to ALL `LuaObject`s.
#### LuaFunction(func_name, func)
The constructor for `LuaFunction` requires the `func_name` to use from within Lua (`nodelua('name')`) as well as the function itself `func`.
```javascript
var func = new nodelua.LuaFunction('test', function(){
console.log('This Is A Test');
return 42;
});
```
#### name
The `name` property of the `LuaFunction` is exposed, but it cannot be changed.
### LuaObject
The `LuaObject` is an object wrapper around a `lua_State` instance.
@ -64,30 +83,32 @@ The `doFile` method is used to load and execute lua code stored in `file_name`.
lua.doFile('test.lua');
```
### doString(lua_code)
#### doString(lua_code)
The `doString` method is the same as `doFile` except the code is loaded from `lua_code` rather than from a file.
```javascript
lua.doString("print('Hello, Lua')");
```
### setGlobal(name, value)
#### setGlobal(name, value)
The `setGlobal` method is used to provide lua with the global variable `name` containing the value `value`.
```javascript
lua.setGlobal('test', 'value');
```
### getGlobal(name)
#### getGlobal(name)
The `getGlobal` method is used to retrieve either a value set by `setGlobal` or a global variable in any lua code that has been run.
```javascript
console.log(lua.getGlobal('test'));
```
### registerFunction(name, func)
`registerFunction` is used to expose a javascript function `func` to lua with the name `name`.
#### registerFunction(func)
`registerFunction` is used to expose a `LuaFunction` `func` to lua.
```javascript
lua.registerFunction('add_them', function(a, b){
var func = new nodelua.LuaFunction('add_them', function(a, b){
console.log(a+b);
});
lua.registerFunction(func);
lua.doString('nodelua("add_them", 2, 4)');
```
There are a few caveats with `registerFunction`.
@ -95,10 +116,9 @@ For starters in order to invoke the javascript function from within lua you must
```lua
nodelua('add_them', 3, 5)
```
All `LuaFunction`s registered with `registerFunction` is registered globally for all `LuaObject`s regardless of which object is used to register it.
As well, there are problems with using `registerFunction` with multiple `LuaObjects`, you will probably end up with a `Segmentation fault: 11` error when running the code. I am working on this issue.
### status()
#### status()
`status` will return the current status code for lua. The result can be `0` for normal or one of the error codes in `nodelua.STATUS`.
```javascript
if(lua.status() == nodelua.STATUS.ERRSYNTAX){
@ -106,13 +126,43 @@ if(lua.status() == nodelua.STATUS.ERRSYNTAX){
}
```
### collectGarbage(GC_CODE)
#### collectGarbage(GC_CODE)
`collectGarbage` is used to control the lua garbage collector. `GC_CODE` should be one of the codes taken from `nodelua.GC`.
```javascript
lua.collectGarbage(nodelua.GC.COLLECT);
```
### close()
#### push(value)
Push `value` onto the Lua stack.
```javascript
lua.push(5);
```
#### pop(num)
Pop `num` items from the stack. Default is 1.
```javascript
lua.pop(5);
```
#### getTop()
Return the number of elements on the Lua stack.
```javascript
var num = lua.getTop();
```
#### setTop(index)
Set the top of the Lua stack to `index`.
```javascript
lua.setTop(3);
```
#### replace(index)
Replaces the top stack element into the specified `index`
```javascript
lua.repalce(3);
```
#### close()
`close` should be used whenever you have finished using a `LuaObject`. This will simply call `lua_close` on the `lua_State` for that object.
## Example
@ -132,10 +182,6 @@ console.dir(lua.getGlobal('some_var'));
lua.close()
```
## TODO
* Currently there are issues with having multiple `LuaObjects`, this is my next task.
* I want to expose the stack functions from lua so it is easy to pop/push objects to lua.
## License
The MIT License (MIT)
Copyright (c) 2012 Brett Langdon <brett@blangdon.com>


+ 5
- 0
example/config/config.lua View File

@ -0,0 +1,5 @@
val_one = 1
val_two = 'two'
val_three = nil
js_value = string.gsub(js_value, 'js_value', 'lua_value')

+ 17
- 0
example/config/index.js View File

@ -0,0 +1,17 @@
var path = require('path');
var nodelua = require('../../');
var lua = new nodelua.LuaObject();
// set a default value
lua.setGlobal('js_value', 'this is js_value');
console.log('js_value: ' + lua.getGlobal('js_value'));
console.log('Processing Config.lua');
var config = path.resolve(__dirname, 'config.lua');
lua.doFile(config);
console.log('js_value: ' + lua.getGlobal('js_value'));
console.log('val_one: ' + lua.getGlobal('val_one'));
console.log('val_two: ' + lua.getGlobal('val_two'));
console.log('val_three: ' + lua.getGlobal('val_three'));

+ 10
- 0
example/constants/index.js View File

@ -0,0 +1,10 @@
var nodelua = require('../../');
console.log('nodelua.INFO');
console.dir(nodelua.INFO);
console.log('nodelua.STATUS');
console.dir(nodelua.STATUS);
console.log('nodelua.GC');
console.dir(nodelua.GC);

+ 0
- 26
example/example.js View File

@ -1,26 +0,0 @@
var path = require('path');
var nodelua = require('../');
console.log('Lua Info:');
console.dir(nodelua.INFO);
var lua = new nodelua.LuaObject();
var func = new nodelua.LuaFunction('test_func', function(a,b){
console.dir(a+b);
});
lua.registerFunction(func);
lua.setGlobal("test", 5);
var test_file = path.resolve(__dirname, 'test.lua');
lua.doFile(test_file);
console.log("Global Var 'global_var' From Lua:");
console.dir(lua.getGlobal('global_var'));
var code = "print('Hello, Lua')";
lua.doString(code);
console.log("Status: " + lua.status());

+ 22
- 0
example/functions/index.js View File

@ -0,0 +1,22 @@
var nodelua = require('../../');
var lua = new nodelua.LuaObject();
var add_them = new nodelua.LuaFunction('add_them', function(a, b){
console.log('Adding ' + a + ' and ' + b + ' in js');
return a + b;
});
lua.registerFunction(add_them);
// Functionas are registered globally
// for all LuaObjects
var lua_two = new nodelua.LuaObject();
lua_two.doString("print('Result in Lua: ' .. nodelua('add_them', 10, 5))");
var subtract_them = new nodelua.LuaFunction('subtract_them', function(a, b){
console.log('Subtracting ' + a + ' and ' + b + ' in js');
return a - b;
});
lua_two.registerFunction(subtract_them);
lua.doString("print('Result in Lua: ' .. nodelua('subtract_them', 10, 5))");

+ 11
- 0
example/simple/index.js View File

@ -0,0 +1,11 @@
var nodelua = require('../../');
var lua = new nodelua.LuaObject();
lua.setGlobal('js_value', 500);
lua.doString('print(js_value)');
lua.doString('js_value = "something new"');
console.dir(lua.getGlobal('js_value'));

+ 0
- 6
example/test.lua View File

@ -1,6 +0,0 @@
print("Calling JS Function 'test_func' From Lua");
nodelua("test_func", 3, 5)
global_var = 'this is a global variable from lua'
print("Global Var 'test' From JS: " .. test)

+ 1
- 1
package.json View File

@ -1,6 +1,6 @@
{
"name": "nodelua",
"version": "0.1.3",
"version": "0.1.4",
"description": "Lua Bindings For Node.JS",
"keywords": [
"lua"


+ 1
- 1
src/luafunction.cc View File

@ -43,7 +43,7 @@ Handle<Value> LuaFunction::New(const Arguments& args) {
LuaFunction* obj = new LuaFunction();
obj->func_name = get_str(args[0]);
obj->func_def_ = Handle<Function>::Cast(args[1]);
obj->func_def_ = Persistent<Function>::New(Handle<Function>::Cast(args[1]));
obj->Wrap(args.This());
return args.This();


+ 1
- 1
src/luafunction.h View File

@ -15,7 +15,7 @@ class LuaFunction : public node::ObjectWrap {
static LuaFunction* unwrap(v8::Handle<v8::Object> handle);
char *func_name;
v8::Handle<v8::Function> func_def_;
v8::Persistent<v8::Function> func_def_;
private:
LuaFunction();
~LuaFunction();


+ 95
- 7
src/luaobject.cc View File

@ -1,5 +1,6 @@
#define BUILDING_NODELUA
#include <node.h>
#include <map>
#include "luaobject.h"
using namespace v8;
@ -7,7 +8,7 @@ using namespace v8;
LuaObject::LuaObject() {};
LuaObject::~LuaObject() {};
Persistent<Object> functions = Persistent<Object>(Object::New());
std::map<char *, Persistent<Function> > functions;
void LuaObject::Init(Handle<Object> target) {
// Prepare constructor template
@ -31,6 +32,16 @@ void LuaObject::Init(Handle<Object> target) {
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<Function> constructor = Persistent<Function>::New(tpl->GetFunction());
target->Set(String::NewSymbol("LuaObject"), constructor);
@ -164,6 +175,79 @@ Handle<Value> LuaObject::SetGlobal(const Arguments& args) {
return scope.Close(Undefined());
}
Handle<Value> 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<LuaObject>(args.This());
push_value_to_lua(obj->lua_, args[0]);
return scope.Close(Undefined());
}
Handle<Value> 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<LuaObject>(args.This());
lua_pop(obj->lua_, pop_n);
return scope.Close(Undefined());
}
Handle<Value> LuaObject::GetTop(const Arguments& args) {
HandleScope scope;
LuaObject* obj = ObjectWrap::Unwrap<LuaObject>(args.This());
int n = lua_gettop(obj->lua_);
return scope.Close(Number::New(n));
}
Handle<Value> 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<LuaObject>(args.This());
lua_settop(obj->lua_, set_n);
return scope.Close(Undefined());
}
Handle<Value> 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<LuaObject>(args.This());
lua_replace(obj->lua_, index);
return scope.Close(Undefined());
}
Handle<Value> LuaObject::RegisterFunction(const Arguments& args){
HandleScope scope;
@ -181,8 +265,7 @@ Handle<Value> LuaObject::RegisterFunction(const Arguments& args){
Handle<Object> handle = Handle<Object>::Cast(args[0]);
class LuaFunction* func = LuaFunction::unwrap(handle);
functions->Set(String::New(func->func_name),
func->func_def_);
functions[func->func_name] = func->func_def_;
return scope.Close(Undefined());
}
@ -198,7 +281,7 @@ int LuaObject::CallFunction(lua_State *L){
lua_error(L);
}
Local<String> func_name = String::New((char *)lua_tostring(L, 1));
char * func_name = (char *)lua_tostring(L, 1);
const unsigned argc = n - 1;
Local<Value>* argv = new Local<Value>[argc];
@ -208,9 +291,14 @@ int LuaObject::CallFunction(lua_State *L){
}
Handle<Value> ret_val = Undefined();
if(functions->Has(func_name)){
Local<Function> func = Local<Function>::Cast(functions->Get(func_name));
ret_val = func->Call(Context::GetCurrent()->Global(), argc, argv);
std::map<char *,Persistent<Function> >::iterator iter;
for(iter = functions.begin(); iter != functions.end(); iter++){
if(strcmp(iter->first, func_name) == 0){
Persistent<Function> func = iter->second;
ret_val = func->Call(Context::GetCurrent()->Global(), argc, argv);
break;
}
}
push_value_to_lua(L, ret_val);


+ 5
- 0
src/luaobject.h View File

@ -30,6 +30,11 @@ class LuaObject : public node::ObjectWrap {
static v8::Handle<v8::Value> Status(const v8::Arguments& args);
static v8::Handle<v8::Value> CollectGarbage(const v8::Arguments& args);
static v8::Handle<v8::Value> Close(const v8::Arguments& args);
static v8::Handle<v8::Value> Push(const v8::Arguments& args);
static v8::Handle<v8::Value> Pop(const v8::Arguments& args);
static v8::Handle<v8::Value> GetTop(const v8::Arguments& args);
static v8::Handle<v8::Value> SetTop(const v8::Arguments& args);
static v8::Handle<v8::Value> Replace(const v8::Arguments& args);
lua_State *lua_;
};


Loading…
Cancel
Save