http://blog.youkuaiyun.com/hopingwhite/article/details/6681826
最近需要使用lua来让策划那些配置一些逻辑,于是调研了一下lua是如何实现这部分工作的,
最终发现一个通常的策划是利用lightuserdata和metatable来协调解决这个问题。也即将数据
指针给lua,另外告诉它一个如何操作这些数据的metamethods即可。
请看下面的示例代码:
- typedef struct
- {
- int x;
- int y;
- int z;
- }TData;
- static int getAttribute(lua_State* L)
- {
- TData *data = (TData*)lua_touserdata(L, 1);
- std::string attribute = luaL_checkstring(L, 2);
- int result = 0;
- if(attribute == "x")
- {
- result = data->x;
- }
- else if(attribute == "y")
- {
- result = data->y;
- }
- else
- {
- result = data->z;
- }
- lua_pushnumber(L, result);
- return 1;
- }
- static struct luaL_reg dataLib[] = {
- {"__index", getAttribute},
- {NULL, NULL}
- };
- void getMetaTable(lua_State* L, luaL_reg* methods)
- {
- lua_pushlightuserdata(L, methods);
- lua_gettable(L, LUA_REGISTRYINDEX);
- if (lua_isnil(L, -1)) {
- /* not found */
- lua_pop(L, 1);
- lua_newtable(L);
- luaL_register(L, NULL, methods);
- lua_pushlightuserdata(L, methods);
- lua_pushvalue(L, -2);
- lua_settable(L, LUA_REGISTRYINDEX);
- }
- }
- int main()
- {
- const char* filename = "test.lua";
- lua_State *lua = lua_open();
- if (lua == NULL)
- {
- fprintf(stderr, "open lua failed");
- return -1;
- }
- luaL_openlibs(lua);
- TData input = {1, 2, 3};
- lua_pushlightuserdata(lua, &input);
- getMetaTable(lua, dataLib);
- lua_setmetatable(lua, -2);
- lua_setglobal(lua, "input");
- if (luaL_dofile(lua, filename))
- {
- luaError(lua, "load file %s failed", filename);
- }
- lua_getglobal(lua, "data");
- int output = lua_tointeger(lua, 0);
- std::cout << output << std::endl;
- return 0;
- }