C++ Lua:从c导出类时的方法和属性

C++ Lua:从c导出类时的方法和属性,c++,oop,methods,properties,lua,C++,Oop,Methods,Properties,Lua,我使用lua作为3d引擎的脚本语言。我有几个对象的lua“类”,现在我想使用属性而不是getter和setter。所以不是像这样的事情 localoldstate=ui:GetChild(“Panel1”):GetVisible() ui:GetChild(“Panel1”):设置可见(非旧状态) 我只是 ui.Panel1.visible=不ui.Panel1.visible 是我的C++代码,用来创建元代码,并例举了超越了x索引方法。顺便说一下,这是: 创建元表: void CLUASc

我使用lua作为3d引擎的脚本语言。我有几个对象的lua“类”,现在我想使用属性而不是getter和setter。所以不是像这样的事情

localoldstate=ui:GetChild(“Panel1”):GetVisible()
ui:GetChild(“Panel1”):设置可见(非旧状态)
我只是

ui.Panel1.visible=不ui.Panel1.visible
<问题>是我的C++代码,用来创建元代码,并例举了超越了x索引方法。顺便说一下,这是:

  • 创建元表:

    void CLUAScript::RegisterClass(const luaL_Reg funcs[],std::string const&className)
    {
    luaL_newmetatable(m_lua_state,std::string(“Classes.”+className).c_str());
    luaL_newlib(m_lua_州,funcs);
    lua_setglobal(m_lua_state,className.c_str());
    }
    
  • > P>实例化类(Lua对象只保存指向C++代码中存储的实际数据的指针):

    int CLUAScript::NewInstanceClass(void*实例,std::string const&className)
    {
    如果(!实例)
    {
    卢阿努普什尼尔(穆卢阿努邦);
    返回1;
    }
    lua_checktype(m_lua_state,1,lua_TTABLE);
    lua_新表(m_lua_状态);
    lua_值(m_lua_状态,1);
    lua_可设置元表(m_lua_状态,-2);
    lua_值(m_lua_状态,1);
    lua_设置字段(m_lua_状态,1,“_索引”);
    void**s=(void**)lua_newuserdata(m_lua_state,sizeof(void*);
    *s=实例;
    luaL_getmetatable(m_lua_state,std::string(“Classes.”+className).c_str());
    lua_可设置元表(m_lua_状态,-2);
    lua_设置字段(m_lua_状态,-2,“_self”);
    返回1;
    }
    
    问题是我如何同时拥有方法和属性。如果我只是将
    \u index
    添加到
    CLUAScript::RegisterClass
    funcs数组中,它永远不会被调用。我无法想象有什么方法可以在
    CLUAScript::NewInstanceClass
    中删除它的重新定义

    如果此代码还不够,以下是指向使用lua的文件的链接: , , ,及

    问题是我如何同时拥有方法和属性

    广义地说,方法只是碰巧解析为函数的属性

    如果我只是将_索引添加到RegisterClass funcs数组中,则永远不会调用它

    这才是真正的问题,对吗?你文章的其余部分会分散你对真实问题的注意力

    根据文件。luaL_newmetatable也是如此。您正在RegisterClass中创建两个表,这毫无意义。您只需要创建元表,您需要将
    \uuuu索引
    \uuu新索引
    元方法添加到此元表

    <>你不能拥有<代码>索引>代码>简单地指向函数表(实现类方法的快捷方式),而不是手动地将数据封送到C++类实例属性中。它需要是一个区分方法访问(值来自类范围)和属性访问(值来自实例范围)的函数


    下面是一个在Lua中如何进行方法/属性访问的示例。使用C API的细节有所不同,但方法是相同的:

    <代码>——这是你在RegisterClass为C++类“Foo”创建的Meta Foo={} 这与C++索引代码在C++代码中的工作方式非常接近, ——除非你必须编写代码来解析C++对象中的哪个字段 --对应于“键”(如果有),并将其推到堆栈上。 函数Foo.\uu索引(实例,键) 本地方法=rawget(Foo,key) 如果方法是 返回方法 结束 返回instance.properties[键] 结束 --这也非常接近,只是如果您希望用户能够向Lua对象添加属性 -与C++对象属性共存,您需要将值写入正确的位置。 函数Foo.\uuu newindex(实例、键、值) instance.properties[key]=值 结束 --这不一定是元表上的方法 函数Foo:new(state) 返回setmetatable({properties=state},self) 结束 --类方法的示例 函数Foo:dump() 打印('dump:',self.x,self.y) 结束 ——用户数据的模拟,C++类的一个实例 cppClassInstance={ x=10, y=20, } obj=Foo:新(cppClassInstance) print(obj.x)——读取'x',解析为cppclasinstance.x obj.x=5150——写入“x”,后者写入cppClassInstance.x 打印(obj.x)——见证我们的变化 obj:dump()--调用类方法
    帮助澄清C++代码和Lua代码之间的连接,什么是代码> UI < />代码>什么代码> UI:GetChild(“PrimeTyNoX”)< /Code >返回?例如,<代码> UI 来自C++ Lead的USER数据,还是“<代码> NewInstanceClass < /代码> > <代码> >自= UDATAAObjult<代码> SET?“UI”是UI元素按钮、面板或整个屏幕的实例。每个元素都可以有子元素,可以使用GetChild(name)方法访问这些子元素。这些子元素也将是UI元素。这是一个表,包含一个C++实例作为USER数据的指针,以及一些由NeWistStCuCasLASS函数返回的Meta表的方法。在这种情况下,“ui”是一个局部变量,表示整个屏幕(ui树的根元素)。如果在lua中使用
    GetChild
    GetVisible
    独立函数,会怎么样?然后,您可以将
    ui.Panel1
    作为语法糖的一种形式,转换为
    GetChild(ui,“Panel1”)
    。问题是并非所有方法都可以用属性替换。这就是为什么我想对同一个实体同时使用方法和属性。至于全局函数,我不认为这是一个很好的解决方案,因为不同的类可以有类似的方法,我要么检查每次调用接收到的对象的类型,做不同的事情,要么为每个类创建不同的函数,这将导致这些函数的复杂名称