博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
<转> lua: userdata的metatable使用
阅读量:7103 次
发布时间:2019-06-28

本文共 2475 字,大约阅读时间需要 8 分钟。

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;

 luaL_getmetatable( L, ”ObjectMetatable“);

 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;

}

出处:
作者:

转载地址:http://uiuhl.baihongyu.com/

你可能感兴趣的文章
hadoop 安装2
查看>>
AM企业即时通讯软件大企业的选择
查看>>
System Center 2012 各模块组件简介及架构图
查看>>
Python 错误和异常小结
查看>>
perl pool ping
查看>>
weblogic10.3.6安装、卸载
查看>>
Struts2+JQuery+Json实例(2)
查看>>
grafana安装
查看>>
mysql“Access denied for user 'root'@'localhost'”问题的解决
查看>>
基于java的分布式爬虫
查看>>
React Native系列——Navigator组件的使用介绍
查看>>
bootstrap 代码
查看>>
jsp自定义标签
查看>>
我的技术博客-公告板!
查看>>
c++大文件读写操作(文件内存映射)
查看>>
nginx 主动防御DDOS***
查看>>
JS学习笔记
查看>>
linux sed seq awk 部分
查看>>
oracle删除168万数据;varchar表示时间;java传参date;传参后的时间保存到秒
查看>>
冰箱保鲜标准出炉,行业或迎新纪元
查看>>