Lua调用C++类要点
来源:互联网 发布:中国网络监督局 编辑:程序博客网 时间:2024/06/01 11:51
Lua相关学习参考链接:点击打开链接
Lua调用C++类要点:
1. 为此类建立一个全局表,表名为类名tbClass;
lua_newtable(L);
intmethods = lua_gettop(L);
lua_pushstring(L,T::className);
lua_pushvalue(L,methods);
lua_settable(L,LUA_GLOBALSINDEX);
2.注册一个key为T::className的metatable,并制定其中的一些成员,用于之后生成的userdata。
//这个表用于userdata(T的对象)的metatable
luaL_newmetatable(L, T::className);
int metatable = lua_gettop(L);
// metatable["__index"] = tbClass
lua_pushliteral(L, "__index");
lua_pushvalue(L, methods);
lua_settable(L,metatable);
// metatable["__tostring"] = tostring_T
lua_pushliteral(L, "__tostring");
lua_pushcfunction(L, tostring_T);
lua_settable(L, metatable);
// metatable["__gc"] = gc_T
lua_pushliteral(L, "__gc");
lua_pushcfunction(L, gc_T);
lua_settable(L,metatable);
3. 为此表指定成员,每个成员的key为类的成员函数名,Value为一个带有闭包的统一函数。比如tbClass[FunName] = thunk,之后可以根据闭包得到具体是调用到哪个函数。闭包中有函数名和相应函数的组合结构(以lightuserdata的形式赋给闭包)。这些类成员函数参数都必须包括lua_State,因为它需要的参数都会在lua堆栈中。
// 为tbClass填充成员函数
for (RegType *l =T::methods;l->name; l++)
{
/* edited by Snaily: shouldn't it be const RegType *l ... ? */
lua_pushstring(L, l->name);
//把(函数名,函数地址)pair以lightuserdata的形式作为C closure的upvalue入栈
lua_pushlightuserdata(L, (void*)l);
//把一个新的C closure 压入堆栈。为upvalue的个数,并指定回调函数统一为thunk lua_pushcclosure(L,thunk, 1);
// tbClass[FunName] = Function
lua_settable(L,methods);
}
4.创建C对象给脚本使用b = Account.new(Account, 30); new是tbClass下的一个函数(另外指定的,不会掉到thunk,这一句会调用到C的一个函数,里面会生成一个C对象,然后创建一个userdata用于关联到这个新生成的C对象。最后为这个userdata绑定上我们上面注册为T::classname的metatable。因为定制了metatable的__index成员,所以当userdata找不到的成员会去调用__index,因为之前我们把__index绑定到tbClass,所以也会调用到tbClass的相应成员。
// 创建一个新的T对象,并创建一个基于userdataType的userdata,其中保护了指向T对象的指针
staticint new_T(lua_State *L)
{
lua_remove(L, 1); // use classname:new(), instead of classname.new()
T *obj = newT(L); // call constructor for T objects
userdataType *ud =
static_cast<userdataType*>(lua_newuserdata(L,sizeof(userdataType)));
ud->pT = obj;// store pointer to object in userdata
luaL_getmetatable(L, T::className); // lookup metatable in Lua registry
lua_setmetatable(L, -2);
return 1;// userdata containing pointer to T object
}
5. 当脚本中指定函数被调用的时候,比如b:deposit(50.30)的时候,b是userdata,它的metatable的__index和tbClass绑定(见4),所以会调用到tbClass的相应成员,就是之前关联的thunk:这个时候L的堆栈里面有这个函数的两个参数,一个是b本身,一个是50.30。b是userdata,可以根据它取出对象的指针。见第4步。另外函数被调用的时候,它相关的upvalue也可以取得到,见步骤3。有了对象指针和相应的函数,调用也不为难了,记住参数50.30是保存在堆栈中传给类的成员函数来取得。
// 所有成员函数都会调用到这里,然后根据upvalue来执行具体的成员函数
staticint thunk(lua_State *L)
{
// stack has userdata, followed by method args
T *obj = check(L, 1);// the object pointer from the table at index 0.
lua_remove(L, 1); // remove self so member function args start at index 1
// get member function from upvalue
RegType *l = static_cast<RegType*>(lua_touserdata(L,lua_upvalueindex(1)));
return (obj->*(l->mfunc))(L);// call member function
}
// 根据指定位置narg获得对象指针,这个userdata是在new_T的时候创建的
staticT *check(lua_State *L,int narg)
{
void *pUserData =luaL_checkudata(L,narg, T::className);
userdataType *ud = static_cast<userdataType*>(pUserData); // 这个是函数的upvalue
if(!ud)
luaL_typerror(L, narg, T::className);
returnud->pT;
}
- Lua调用C++类要点
- [Lua]C/C++调用Lua
- [lua]C调用lua函数
- lua调用c++类
- C/C++ 调用 Lua
- c调用lua脚本
- Lua调用C函数
- C调用lua
- lua 调用c函数
- lua c/c++ 调用
- Lua调用C函数
- lua调用c函数
- Lua调用C函数
- c调用lua
- c 调用 lua
- c、c++调用lua
- c/c++ 调用lua
- lua调用C函数
- 成员指针
- SharePoint 2013 : The SDDL string contains an valid sid or a sid cannot be translated
- strcpy实现方式
- PEP20之python之禅
- STL 查找vector容器中的指定对象:find()与find_if()算法
- Lua调用C++类要点
- Uboot常用命令
- 面试知识点-- 操作系统执行可执行程序时,内存分配是怎样的?
- linux 环境 c 连接mysql笔记
- VS2010中GetMenu()和GetSubMenu(0)为NULL引发异常的解决方法
- TCP协议的作用?三次握手是通过什么方法来保证通信双方确认的正确?
- CSS Sprite的应用
- KMP与Sunday算法
- QT类的继承结构