【问题标题】:Lua C++ userdata matrix access to elementsLua C++ 用户数据矩阵访问元素
【发布时间】:2015-12-14 23:33:12
【问题描述】:

我在C++中有一个矩阵类,构造函数如下:

template <typename T> CMatrix<T>::CMatrix(unsigned int varrow,unsigned int varcolumn)
{
        //Lets set member variables
        this->m_row=varrow;this->m_column=varcolumn;

        //Create a place holder at heap
        m_matrix=new T[varrow*varcolumn];
        //
        unsigned int i=0;
        //
        //Default matrix All elements are zero

            for(i=0;i<varrow*varcolumn;i++)
            {
                    m_matrix[i]=T();
            }

        //
    }

我已经实现了 set 和 get 方法如下:

void SetCellValue(unsigned int row,unsigned int col,T value){ m_matrix[row*m_column+col]=value;}
T& GetCellValue(unsigned int row,unsigned int column) const{return m_matrix[row*m_column+column];}

矩阵类可以从 Lua 访问;但是,我可以从 Lua 访问矩阵元素的唯一方法是,如果 m 是矩阵,m:GetValue 或 m:SetValue。

我想知道是否可以通过符号 m[1,2] 或 m(1,2) 访问(设置)矩阵元素,其中 m 是矩阵,[1,2] 是第一行第二列。

【问题讨论】:

    标签: c++ lua lua-api meta-method


    【解决方案1】:

    有两个基本问题。 lua 语法和 lu​​a 语义。

    语法

    就语法而言,m(1,2) 绝对是可能的,如果您使用 userdata 的 __call 元方法。

    我不认为m[1,2] 是可能的,我认为这不可能是有效的lua。如果您使用 __index 元方法,则可以使用 m[{1,2}]

    语义

    基本问题是 lua 与 javascript、java 和其他非 C++ 语言一样,使原始整数成为值类型而不是引用类型。

    所以你可以很容易地让m(1,2) 返回正确的整数,但是如果你想写m(1,2) = 5,那就更难了,因为m(1,2) 只返回一个副本,而不是一个引用。

    在 Java 中(饱受诟病的)解决方案是使用 Boxing,将原始类型包装在一个类中,以便为其提供正确的(引用)语义。这里的类比是您不返回一个 int,而是返回一个包含对矩阵中的 int 的引用的 userdata。

    在 lua 中,您通常使用 __index__newindex 元方法来避免这种情况。 __index 在您从 userdata 请求子值时调用,__newindex 在您分配 userdata 的子值时调用。所以不需要装箱,你可以给它任何你想要的语义。

    问题在于,在这种情况下,__index__newindex 会给你带来难看的语法,你必须使用 m[{1,2}]m[{1,2}] = 5 才能让它以这种方式工作。

    选项

    因此,选项 (1) 是,为您拥有的任何类型实施某种装箱,并使用 __call 元方法。

    选项(2)是,只需使用__index__newindex 并习惯写m[{1,2}]

    选项(3)是,尝试使用不同的语法m[1][2]。然后你会想要创建一个代表矩阵行的新类,并通过m[1] 将其暴露给lua。然而,这也增加了一些复杂性,有各种原因你不想这样做。 (并且您在 cmets 中表示您并不想这样做。)

    如果他们扩展了 lua 语言,那么最好的事情就是 m[1,2] 只是 m[{1,2}] 或类似的语法糖。但是,我不会屏住呼吸。

    如果是我,选项(3)是不可能的,我想我会选择选项(2)并习惯它。想看看是否有人知道改进它。

    【讨论】:

    • 我从未使用过 LUA,但我想知道他是否不能只为他的矩阵类实现 element&amp; operator(int,int) 以获得所需的行为
    • 我尝试了第一个选项,它有效,但正如您所说,它不适用于m(1,2)=5。我想知道使用 __call 和 __eq 之类的嵌套元表是否有意义,以便前面的表达式可以工作。您的第二个建议是一个很好的建议,但我不想将 RowVector 公开给 Lua,并且不知道如何在不向 Lua 开放的情况下执行此操作
    • 有没有办法获取赋值右侧的值;例如,我可以让m(1,2) 工作,如果我能以某种方式读取= 之后的值,那么操作m(1,2)=5 将很容易。
    • 不,在 lua 中没有办法做到这一点。 lua 没有 C++ 中的“复制赋值运算符”。一个简单的赋值a = b 总是只分配值/进行引用。如果您分配给具有元表的表的索引,则可以通过__newindex 捕获分配,仅此而已。 (从技术上讲,如果全局表_G 具有元表,则可以捕获a = b。但无法捕获m(1,5) = b,左侧不是任何表的索引。)
    • 由于没有更多关于这个问题的评论,我想接受你的全面。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-12
    • 2022-10-24
    • 1970-01-01
    • 2023-04-05
    • 2021-12-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多