如何封装c++的指针
来源:互联网 发布:奇迹暖暖每章套装知乎 编辑:程序博客网 时间:2024/05/29 16:30
1 如何封装c++的指针
对于c++对象的lua包装,我们可以使用
template<typename T>
struct luaUserdataWrapper
{
luaUserdataWrapper() {}
luaUserdataWrapper(const T& d) : data(d) {}
T data;
};
class CObject
{
public:
int v[10];
};
typedef luaUserdataWrapper<CObject*> luaObject;
这样就可以在c代码中,按照如下方法向lua中添加生成CObject的对象的C函数:
int NewObject( lua_State* L )
{
luaObject* wrapper = (luaObject*) lua_newuserdata( L, sizeof(luaObject) );
wrapper->data = new CObject;
return 1;
}
lua_newuserdata函数把wrapper存放在栈顶位置,作为NewObject的返回值。
wrapper的生存期由lua负责,而wrapper->data的生命期则由程序员自己负责。
在lua代码中的使用方法是:
obj = NewObject() --调用C函数
2 使用metatable
如果此时我们想在lua中使用如下语法:
obj[5]=20
value = obj[5]
则需要我们为luaObject添加metatable属性。
步骤1:
在lua代码中的普通表,不能作为userdata的metatable。必须使用luaL_newmetatable创建的表才能作为userdata的metatable。
在openlib函数中,添加一个userdata 的 metatable表,
int OnOpenlib( lua_State* L )
{
...
luaL_newmetatable( L, “ObjectMetatable");
}
luaL_newmetatable把新创建的表放在栈顶。
注意:新创建的ObjectMetatable表仅在栈中被声明,并没有加入到lua代码中。如果在以后的lua代码中使用ObjectMetatable.__index等操作,会提示ObjectMetatable:a nil value。
步骤2:
这是我们重写上面的New方法。
int NewObject( lua_State* L )
{
luaObject* wrapper = (luaObject*) lua_newuserdata( L, sizeof(luaObject) );
wrapper->data = new CObject; //创建userdata表
luaL_getmetatable( L, ”ObjectMetatable“); //设置userdata的元表
lua_setmetatable( L, -2 );
return 1;
}
这样我们就为新生成的luaObject对象添加metatable。
luaL_getmetatable( L, ”ObjectMetatable“)获取ObjectMetatable表,并放入栈顶。
lua_setmetatable( L, -2 )则把新生成的userdata的metatable设置为ObjectMetatable。
步骤3:
value = obj[5]的取下标操作对应的是__index域,而
obj[5]=2;对应的是__newindex域。
所以我们需要添加ObjectMetatable的__index,__newindex域。
我们重写int OnOpenlib( lua_State* L )方法
int OnOpenlib( lua_State* L )
{
...
luaL_newmetatable( L, “ObjectMetatable");
lua_pushstring( L, "__index" );
lua_pushcfunction( L, GetValue );
lua_rawset( L, -3 ); // ObjectMetatable.__index = GetHorizonValue
lua_pushstring( L, "__newindex" );
lua_pushcfunction( L, SetValue );
lua_rawset( L, -3 ); // ObjectMetatable.__newindex = GetHorizonValue
}
GetValue 与SetValue 是自定义的C函数,可以不用被注册到lua代码中。
在lua中调用
v=obj[5]
时,会触发元函数metatable.__index,obj、5会被依次入栈。
所以GetValue方法我们可以写为
int GetValue(lua_State* L)
{
luaL_checktype(L, -1, LUA_TNUMBER);
luaL_checktype(L, -2, LUA_TUSERDATA);
luaObject* wrapper = (luaObject*) lua_touserdata(L, -2);
ASSERT( wrapper->data != NULL );
if ( wrapper->data == NULL )
{
lua_pushstring( L, "GetHorizonValue: NULL wrapper " );
lua_error(L);
return 1;
}
int index = (int)(float)lua_tonumber(L, -1);
int value = wrapper->data.v[index];
lua_pushnumber( L, value );
return 1;
}
- 如何封装c++的指针
- C指针的指针
- c 指针的指针
- [C/C++]如何解读返回函数指针的函数声明
- [C/C++]如何解读返回函数指针的函数声明
- 高质量c++(指针参数是如何传递内存的?)
- C语言数组和指针是如何访问的
- 高质量c++(指针参数是如何传递内存的?)
- c++(指针参数是如何传递内存的?)
- 【c++】指针参数是如何传递内存的
- 如何解决C/C++返函数指针的函数声明
- 【c++】指针参数是如何传递内存的
- 【c++】指针参数是如何传递内存的
- 【c++】指针参数是如何传递内存的
- 如何读懂C语言指针
- 如何读懂c语言指针
- 如何理解c++this指针
- 如何理解指针的指针
- KVM源代码分析3:CPU虚拟化
- poj2253Frogger(最短路变形)及poj1797Heavy Transportation(最大生成树)
- Android 判断日期是否在一年以内的算法
- Android studio 百度地图demo出现230错误,key校验失败
- 使用Reveal查看任意App最省步骤的技巧
- 如何封装c++的指针
- springmvc + mybatis+mysql 分页
- binbinyang-----CircleImageView自定义圆形控件的使用
- bower简明入门
- Glide介绍及源码解析二
- LMAP
- 浅谈微信卡券功能开发(2)
- 1012. 数字分类 (20)
- 【python新手入门】一个python List 的简单运用 -----班级学生管理系统