Lua 任意类型的get/set方法
来源:互联网 发布:淘宝怎么回收手机 编辑:程序博客网 时间:2024/05/17 19:56
Lua任意类型的get/set方法
对于lua与C程序相互调用时,如果有一个数字需要在C程序和lua脚本同时使用,这时就需要保持lua程序与C程序中的数字变量一致,及当C程序改变了这个数字变量时lua能够获取改变后的值,当lua程序改变了变量时C程序也可以获取改变后的值。实现这个功能可以给lua变量设置get/set方法。当lua中读取数字变量的值时,则调用对应得get方法,get方法中可以调用C程序中的一个get获取到C程序中数字变量的值,同理给数字变量赋值时也一样。这样lua中使用的数字变量的值就是C程序中的变量值,从而保持一直。
使用lua实现get/set方法
Lua本身并没有提供get/set类的方法,但可以通过环境表元表的__index和__newindex方法实现。当获取一个global变量时,实际上是通过变量名为索引从环境表中获取值,如果环境表中没有变量时会去调用相应的__index方法。所以要实现get/set方法可以将变量存于另一个表,在环境表中不保存相应的变量,在环境表的__index方法中根据变量去查找并调用相应的get/set方法。具体实现如下。
function attr_setup() local handlers = {} --存储get和set方法local values = {} --存储值 local mt = { __index = function(t, k) local h = handlers[k]print("get", k) return h and h.get() end, __newindex = function(t, k, v) local h = handlers[k]print("set", k) if h then return h.set(v) else values[k] = vhandlers[k] = {set = function(v) values[k] = v end, get = function() return values[k] end} end end, } setmetatable(getfenv(), mt)--将当前环境的元表设为 mt,getfenv()只使用于lua5.1以前的版本,5.2以后请使用_ENV 变量endattr_setup()print(c) -->nilprint(type(c), "\n\n") -->nila = 15print(a) -->15print(type(a), "\n\n")--numberb = { x = 10};print(b.x) -->10print(type(b), "\n\n")-->tableprint("rawget(_G, \'b\')", rawget(_G, 'b')) -->nil
C代码实现
C代码
#include<iostream>extern "C" {#include "lua\lua.h"#include "lua\lualib.h"#include "lua\lauxlib.h"}using namespace std;const char *HandlesGetSet = "HandlesGetSet";double a = 166;int a_get(lua_State*L){lua_pushnumber(L, a);return 1;}int a_set(lua_State *L){if (lua_isnumber(L, 1)){a = lua_tonumber(L, 1);}return 0;}int index_event(lua_State*L){//从 registry 中获取变量的get set 方法luaL_getmetatable(L, HandlesGetSet);lua_pushvalue(L, 2);lua_rawget(L, -2);if (lua_isnil(L, -1))// 没有get set方法{lua_pop(L, 2);lua_rawget(L, -2);}else{lua_pushstring(L, "get");lua_rawget(L, -2);lua_pcall(L, 0, 1, 0);//调用get方法}return 1;}int newindex_event(lua_State *L){//从 registry 中获取变量的get set 方法luaL_getmetatable(L, HandlesGetSet);lua_pushvalue(L, 2);lua_rawget(L, -2);if (lua_isnil(L, -1))// 没有get set方法{lua_pop(L, 2);lua_rawset(L, -3);}else{lua_pushstring(L, "set");//调用set方法lua_rawget(L, -2);lua_pushvalue(L, 3);lua_pcall(L, 1, 0, 0);}return 0;}int main(){lua_State *L = luaL_newstate();luaL_openlibs(L);//获取 _G表#if defined (LUA_VERSION_NUM) && LUA_VERSION_NUM >= 502 /* after lua 5.2 */lua_pushvalue(L, LUA_REGISTRYINDEX); /* registry */lua_pushnumber(L, LUA_RIDX_GLOBALS); /* registry globalsindex */lua_rawget(L, -2); /* registry registry[globalsindex] */lua_remove(L, -2); /* registry */#elselua_pushvalue(L, LUA_GLOBALSINDEX);#endif//创建 _G表的元表lua_newtable(L);lua_pushstring(L, "__index");lua_pushcfunction(L, index_event);lua_rawset(L, -3);lua_pushstring(L, "__newindex");lua_pushcfunction(L, newindex_event);lua_rawset(L, -3);lua_setmetatable(L, -2);//设置 _G表的元表lua_pop(L, 1);//创建一张表存储在 registry 中luaL_newmetatable(L, HandlesGetSet);//注册 a 变量的get set方法lua_pushstring(L, "a");lua_newtable(L);lua_pushstring(L, "get");lua_pushcfunction(L, a_get);lua_rawset(L, -3);lua_pushstring(L, "set");lua_pushcfunction(L, a_set);lua_rawset(L, -3);lua_rawset(L, -3);lua_pop(L, 1);a = 99;if (0 != luaL_dofile(L, "a.lua")){printf("%s\n", lua_tostring(L, -1));}printf("a = %f\n\n\n", a);a = a+1000;if (0 != luaL_dofile(L, "a.lua")){printf("%s\n", lua_tostring(L, -1));}printf("a = %f\n", a);lua_close(L);return 0;}
测试用的 “a.lua”文件
print(a)a = a+1print("c=", c)b = "adas"print("b=", b)
运行结果:
阅读全文
0 0
- Lua 任意类型的get/set方法
- get/set方法的使用
- Get Set 方法的理解
- kotlin 的get() set() 方法
- get方法和set方法的使用!
- OC基础—————类型的可见度,封装,自定义方法, set 和 get
- 类型安全的 C++/Lua 任意参数互调用
- Java获得基类各个属性、类型 、get/set方法
- struts2的get,set方法的作用。
- 万恶的Struts的get set方法
- DataBinding中get,set方法的使用
- MyEclipse的自动生成get, set 方法
- vb.net 的get ,set方法
- JavaBean的get、set方法生成器
- 重写RadioGroup的get和set方法
- set与get方法的区别
- oc中get set 方法的实现
- JS属性的get和set方法
- CAS 与乐观锁
- Lintcode73 Construct Binary Tree from Preorder and Inorder Traversal solution 题解
- bzoj1034: [ZJOI2008]泡泡堂BNB
- C++ 日期 & 时间
- java抽象类
- Lua 任意类型的get/set方法
- acos
- 【剑指Offer_在线编程】 【牛客网22题:二叉搜索树的后序遍历序列】
- StackOverflow和OutOfMemory
- poj1416——Shredding Company
- Set集合的练习
- 02 理解Django框架下MTV模式(2)
- 7.Spark Streaming:输入DStream之基础数据源以及基于HDFS的实时wordcount程序
- 使用回调函数实现qsort(冒泡排序)