[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: RE: Application extension API suggestions
- From: "John Dunn" <John_Dunn@...>
- Date: Thu, 29 Nov 2007 15:02:25 -0800
Thanks you for the comments.
> A reasonable solution. I would add a bit of syntactic sugar:
>
> print(object.value) -- instead of object:getValue()
> object.value = 42 -- instead of object:setValue(42)
>
> by writing an adequate __index metamethod. The bonus of such
> a syntax, beyond it's lightness, is abstraction over keys.
> That is, you can use object[key] where key varies programmatically.
I haven't had any luck attempting to do the above. My object is userdata
and if I attempt to access a field on the userdata with the '.' it
errors with the following -
error : [string "Controls.Inputs[1].value = 1111"]:1: attempt to
index field '?' (a userdata value)
I assume there is some issue with the way I'm registering my tables but
I haven't figured out exactly what the problem is. My code is below - if
you have any suggestions they'd be much appreciated.
The script comments were helpful. Not only am I new to embedding lua but
I'm also new to Lua itself. Thanks.
John
#include <iostream>
#include <lua/lauxlib.h>
#include <lua/lualib.h>
#include <lua/lua.h>
const char* MyObjectID = "Test.Object";
const char* MyObjectClass = "Object";
struct MyObject
{
double value;
MyObject() : value( rand() )
{
}
double get_value() { return value; }
void set_value( double d ) { value = d; }
};
static int getValue( lua_State* L )
{
MyObject* obj = *(MyObject**)luaL_checkudata(L,1, MyObjectID);;
lua_pushnumber(L,obj->value);
return 1;
}
static int setValue( lua_State* L )
{
MyObject* obj = *(MyObject**)luaL_checkudata(L,1, MyObjectID);;
obj->value = luaL_checknumber(L,2);
return 1;
}
static int index( lua_State* L )
{
const char* key = luaL_checkstring(L, 2);
std::cout << "in __index, key is " << key << std::endl;
lua_getmetatable(L, 1);
lua_getfield(L, -1, key);
// Either key is name of a method in the metatable
if(!lua_isnil(L, -1))
return 1;
// ... or its a field access - do something based on field name
here ...
std::cout << "field access ahoy!" << std::endl;
return 1;
}
static const struct luaL_reg MyObjectInstanceMethods[] =
{
{ "getValue", getValue },
{ "setValue", setValue },
{ "__index", index },
{NULL,NULL}
};
int luaMyObjectOpen( lua_State* lua )
{
// register metatable for MyObject
luaL_newmetatable( lua, MyObjectID );
lua_pushvalue( lua, -1 );
lua_setfield( lua, -1, "__index");
luaL_register(lua, NULL, MyObjectInstanceMethods );
return 1;
}
void check_status( lua_State* lua, int status )
{
if( status )
{
const char* msg = lua_tostring(lua, -1);
lua_pop(lua, 1);
std::cout << "error : " << msg << std::endl;
}
}
int main( int argc, char** argv ) {
lua_State* L = luaL_newstate();
luaL_openlibs(L);
luaMyObjectOpen(L);
// add an object
MyObject** ptr = (MyObject**)lua_newuserdata(L,sizeof(MyObject*));
*ptr = new MyObject();
// set metatable
luaL_getmetatable(L,MyObjectID);
lua_setmetatable(L,-2);
lua_setglobal(L,"MyObject");
// these work
check_status( L, luaL_dostring( L, "print( MyObject:getValue())" ));
check_status( L, luaL_dostring( L, "MyObject:setValue(1234)" ));
// this doesn't work
check_status( L, luaL_dostring( L, "print( MyObject:Value )" ));
// or this
check_status( L, luaL_dostring( L, "print( MyObject.Value )" ));
// or this
check_status( L, luaL_dostring( L, "MyObject:Value = 3333" ));
// or this
check_status( L, luaL_dostring( L, "MyObject.Value = 3333" ));
lua_close(L);
return 0;
}