1 如何封裝c++的指針c++
對於c++對象的lua包裝,咱們能夠使用程序員
template<typename T>
struct luaUserdataWrapper
{
luaUserdataWrapper() {}
luaUserdataWrapper(const T& d) : data(d) {}app
T data;
};函數
class CObjectlua
{指針
public:對象
int v[10];
};get
typedef luaUserdataWrapper<CObject*> luaObject;string
這樣就能夠在c代碼中,按照以下方法向lua中添加生成CObject的對象的C函數:io
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;
}