Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Lua/C++;:__即使是表';s场是已知的 我想在Lua申报一个由C++应用程序注册的全球元数据库。 我定义了Meta和某些字段的y-索引索引,但当Lua脚本访问已知字段时,总是在我的C++应用程序中调用y-索引。< /p>_C++_Lua - Fatal编程技术网

Lua/C++;:__即使是表';s场是已知的 我想在Lua申报一个由C++应用程序注册的全球元数据库。 我定义了Meta和某些字段的y-索引索引,但当Lua脚本访问已知字段时,总是在我的C++应用程序中调用y-索引。< /p>

Lua/C++;:__即使是表';s场是已知的 我想在Lua申报一个由C++应用程序注册的全球元数据库。 我定义了Meta和某些字段的y-索引索引,但当Lua脚本访问已知字段时,总是在我的C++应用程序中调用y-索引。< /p>,c++,lua,C++,Lua,例如,我想注册一个名为User的全局表,它包含三个字段:FirstName、LastName和Age 这是我登记表格的方式。该表封装在一个名为TLuaStruct的类中,这使得在Lua中注册表变得更容易 bool TLuaStruct::InternalRegister( std::string tName, bool AddInGC ) { TLuaStack *ptStack; TLuaStruct **ptUserLuaStruct; ptStack = m_pt

例如,我想注册一个名为User的全局表,它包含三个字段:FirstName、LastName和Age

这是我登记表格的方式。该表封装在一个名为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;
}

如果将Meta本身分配给了一个C回调,那么脚本可以读取只读的名字、LASTEND和AGED(我想做什么),但是我不知道脚本何时访问未知字段,因为我的C++应用程序没有被调用。 也许Lua总是在元表为userdata时调用_索引,以确保值是最新的,但最好定义只读变量,如表中的函数,否则一直调用_索引会降低应用程序的速度

有人知道怎么做吗?
谢谢。

该手册很好地解释了元表的工作原理,也许您误读了它-元表中的任意字段没有效果,只有
\u index
向对象添加了“假”字段

最好的解决方案是将所有静态值放入
\uuu索引
表中,然后为
\uu索引
表创建另一个元表,并将其
\uu索引
字段设置为您的函数

更新:
正如其他人所提到的,存在一个稍微紧凑的解决方案:将第一个元表的
\uu索引设置为自身(并用静态值填充),然后将其元表设置为另一个元表,该元表的功能是作为其
\uu索引
解决方案:

Riv的解决方案几乎是正确的,但有一点不同,所以我发布了一个新的答案

解决方案是将主元表的_索引设置为自身,创建第二个元表,其中其_索引设置为C回调函数,并将此新元表设置为主元表的元表而不是其_索引

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 const members 
    PushProperties( false, false );

    //  Duplicate the metatable
    //  Stack after the call:
    //  2,-1 | table
    //  1,-2 | table
    ptStack->PushValue( -1 );

    //  Set its __index to itself so it can access all of its const members
    //  Stack after the call:
    //  1,-1 | table
    m_ptLua->SetField( -2, "__index" );


    //  Create another metable that will be used for non-const members
    //  Stack after the call:
    //  2,-1 | table
    //  1,-2 | table
    m_ptLua->NewMetaTable( "9999" );

    //  Push the C call back called when a non-const member is read
    //  Stack after the call:
    //  3,-1 | function
    //  2,-2 | table
    //  1,-3 | table
    ptStack->PushCFunction( TLuaStruct_Index_CallBack );

    //  Set the __index of the metable
    //  Stack after the call:
    //  2,-1 | table
    //  1,-2 | table
    m_ptLua->SetField( -2, "__index" );


    //  Set the metatable of the main metatable
    //  Stack after the call:
    //  1,-1 | table
    m_ptLua->SetMetaTable( -2 );

    // Create a UserData to store the address of this.
    //  Stack after the call:
    //  2,-1 | userdata
    //  1,-2 | table
#warning check whether we must create a new pointer each time...
    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 );

    //  Set the metatable of the userdata
    //  Stack after the call:
    //  1,-1 | userdata
    m_ptLua->SetMetaTable( -2 );

    //  Publish the userdata object with the name of the module.
    //  Stack after the call:
    //  -- empty --
    m_ptLua->SetGlobal( tName.c_str() );

    return true;
}

我已经尝试创建一个元表#1,将我的静态值放入其中,创建另一个元表#2,将我的函数放入其#索引中,然后将元表#2放入元表#1的#索引中,最后使用元表#1设置userdata的元表。但这根本不起作用,这是最糟糕的。你能提供一个样品吗?我试着在Lua脚本中这样做,它工作得很好,但在C语言中不行,我猜我做错了什么,但我仍然不知道是什么。不要给问题添加答案,让问题保持原样。相反,对你自己的问题发布一个答案。是的,但里夫的答案也几乎是正确的。@A.G.我同意于浩的观点,你应该发布答案。您不必将其标记为已接受答案,您可以将Riv保留为已接受答案。您的答案很可能会被提升,从而让其他新加入此线程的人知道它也应该被考虑。你的答案与你的问题一致,没有办法区分你的答案和问题的价值。只是注意,使用“静态”和“动态”成员的单词要小心:静态意味着C++中的非堆栈或类宽(你正在使用)和许多其他的OO语言。从外观上看,您的意思是只读或常量,即它们的值不能更改,或者无法从对象/表中删除成员(在Lua中,这意味着设置为零)。@Scholli:你说得对,我将更改我的帖子。