Luna Wrapper 导出类

来源:互联网 发布:最全网络理财投资 编辑:程序博客网 时间:2024/04/29 16:39

Luna Wrapper

lua-users homewiki


LunaWrapper is a short (53-line) wrapper to provide access to C++ classes from within Lua with relative ease. Inspired by[1], updated for Lua 5.1. Written by nornagon. Download:[2]

LunaFour provides additional features such as properties (requires modification to Lua) and functions for retrieving and returning classes from C++.

 

template<class T> class Luna {  public:    static void Register(lua_State *L) {      lua_pushcfunction(L, &Luna<T>::constructor);      lua_setglobal(L, T::className);      luaL_newmetatable(L, T::className);      lua_pushstring(L, "__gc");      lua_pushcfunction(L, &Luna<T>::gc_obj);      lua_settable(L, -3);    }    static int constructor(lua_State *L) {      T* obj = new T(L);      lua_newtable(L);      lua_pushnumber(L, 0);      T** a = (T**)lua_newuserdata(L, sizeof(T*));      *a = obj;      luaL_getmetatable(L, T::className);      lua_setmetatable(L, -2);      lua_settable(L, -3); // table[0] = obj;      for (int i = 0; T::Register[i].name; i++) {        lua_pushstring(L, T::Register[i].name);        lua_pushnumber(L, i);        lua_pushcclosure(L, &Luna<T>::thunk, 1);        lua_settable(L, -3);      }      return 1;    }    static int thunk(lua_State *L) {      int i = (int)lua_tonumber(L, lua_upvalueindex(1));      lua_pushnumber(L, 0);      lua_gettable(L, 1);      T** obj = static_cast<T**>(luaL_checkudata(L, -1, T::className));      lua_remove(L, -1);      return ((*obj)->*(T::Register[i].mfunc))(L);    }    static int gc_obj(lua_State *L) {      T** obj = static_cast<T**>(luaL_checkudata(L, -1, T::className));      delete (*obj);      return 0;    }    struct RegType {      const char *name;      int(T::*mfunc)(lua_State*);    };};class Foo {  public:    Foo(lua_State *L) {      printf("in constructor/n");    }    int foo(lua_State *L) {      printf("in foo/n");    }    ~Foo() {      printf("in destructor/n");    }    static const char className[];    static const Luna<Foo>::RegType Register[];};const char Foo::className[] = "Foo";const Luna<Foo>::RegType Foo::Register[] = {  { "foo", &Foo::foo },  { 0 }};

 

Then somewhere during initialization:

 

Luna<Foo>::Register(L);

From lua:

 

local foo = Foo()foo:foo()

Later:

 

lua_close(L);

Results:

 

in constructorin fooin destructor

 

See Also

 

  • BindingCodeToLua

 

Note

If you directly want to create the class in Lua and get a pointer back to set some values then you can add this function to the Luna class. I am new to implementing Lua to C++ so there is probably a better way for doing this and I am happy to see the approaches.

// Directly add the new classstatic T* RegisterTable(lua_State *L){luaL_newmetatable(L, T::className);lua_pushstring(L, "__gc");lua_pushcfunction(L, &Luna<T>::gc_obj);lua_settable(L, -3);T* obj = new T(L);lua_newtable(L);lua_pushnumber(L, 0);T** a = (T**)lua_newuserdata(L, sizeof(T*));*a = obj;luaL_getmetatable(L, T::className);lua_setmetatable(L, -2);lua_settable(L, -3); // table[0] = obj;for (int i = 0; T::Register[i].name; i++){lua_pushstring(L, T::Register[i].name);lua_pushnumber(L, i);lua_pushcclosure(L, &Luna<T>::thunk, 1);lua_settable(L, -3);}lua_setglobal(L, T::className);return obj;}
原创粉丝点击