【发布时间】:2013-12-18 09:50:50
【问题描述】:
我想在 Lua 中声明由 C++ 应用注册的全局元表。
我定义了元表和一些字段的 __index 元方法,但是当 lua 脚本访问已知字段时,__index 总是在我的 C++ 应用程序中调用。
例如,我想注册一个名为 User 的全局表,其中包含三个字段:FirstName、LastName 和 Age em>。
这是我注册表格的方法。该表被封装在一个名为 TLuaStruct 的类中,这使得在 Lua 中注册表更容易。
bool TLuaStruct::InternalRegister( std::string tName, bool AddInGC )
{
TLuaStack *ptStack;
TLuaStruct **ptUserLuaStruct;
ptStack = m_ptLua->GetStack();
if( ptStack==NULL )
return false;
// Create a metatable that won't be exposed to Lua scripts.
// The name must be unique
// Stack after the call:
// 1,-1 | table
m_ptLua->NewMetaTable( m_tMetaName );
// Register all of the properties
PushProperties( false, false );
// Register the callback assigned to __index
ptStack->PushCFunction( TLuaStruct_Index_CallBack );
m_ptLua->SetField( -2, "__index" );
// Create a UserData to store the address of this.
// Stack after the call:
// 2,-1 | userdata
// 1,-2 | table
ptUserLuaStruct = ( TLuaStruct** )m_ptLua->NewUserData( sizeof( ptUserLuaStruct ) );
*ptUserLuaStruct = this;
m_pvLuaThisPtr = ( void* )ptUserLuaStruct;
// Switch the userdata and the table
// Stack after the call:
// 2,-1 | table
// 1,-2 | userdata
ptStack->Insert( -2 );
// Associate the metatable to the userdata
// Stack after the call:
// 1,-1 | userdata
m_ptLua->SetMetaTable( -2 );
m_ptLua->SetGlobal( tName.c_str() );
return true;
}
如果我将元表本身分配给 __index 而不是 C 回调,则脚本可以只读方式访问 FirstName、LastName 和 Age (我想做什么)但我不知道脚本何时尝试访问未知字段,因为我的 C++ 应用程序没有被调用。
当元表是用户数据时,也许 Lua 总是调用 __index 以确保值是最新的,但是在表中定义只读变量(例如函数)可能会很好,否则一直调用 __index 会变慢关闭应用程序。
有人知道如何执行此操作吗? 谢谢。
【问题讨论】:
-
不要将解决方案添加到问题中,让问题保持原样。相反,请发布您自己问题的答案。
-
是的,但是 riv 的回答也几乎是对的。
-
@A.G.我同意于浩,你应该发布答案。您不必将其标记为已接受的答案,您可以将 Riv 保留为已接受。您的答案可能会被投票,从而让其他新加入该主题的人知道也应该考虑它。由于您的答案与您的问题一致,因此无法区分您的答案与问题的价值。
-
请注意,使用“静态”与“动态”成员这两个词时要小心:在 C++(您正在使用)和许多其他 OO 语言中,静态表示非堆栈或类范围。从表面上看,您的意思是只读或 const,即它们的值不能改变,或者不能从对象/表中删除成员(在 Lua 中意味着设置为 nil)。
-
@Scholli:你说得对,我会改变我的帖子。