Lua C++ 用户数据矩阵访问元素
Lua C++ userdata matrix access to elements
我有一个C++矩阵class,构造函数如下:
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();
}
//
}
我实现了如下设置和获取方法:
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];}
矩阵 class 可从 Lua 访问;但是,我可以从 Lua 访问矩阵元素的唯一方法是,如果 m 是矩阵,m:GetValue 或 m:SetValue。
我想知道是否可以通过符号 m[1,2] 或 m(1,2) 访问(设置)矩阵元素,其中 m 是矩阵,[1,2] 是第一行第二列的元素。
有两个基本问题。 lua 语法和 lua 语义。
语法
就语法而言,如果您使用用户数据的 __call
元方法,m(1,2)
绝对是可能的。
我认为 m[1,2]
不可能,我认为那不可能 lua。如果您使用 __index
元方法,则可以使用 m[{1,2}]
。
语义
基本问题是 lua,如 javascript、java 和其他非 C++ 语言,使原始整数成为值类型而不是引用类型。
所以你可以很容易地让m(1,2)
return成为正确的整数,但是如果你想写m(1,2) = 5
,那就更难了,因为m(1,2)
只有return是副本,不是参考。
在 Java 中,(饱受诟病的)解决方案是使用装箱,将原始类型包装在 class 中,以便为其提供正确的(参考)语义。这里的类比是你没有 return 一个 int,你 return 一个用户数据,它在你的矩阵中包装了一个对 int 的引用。
在 lua 中,您通常使用 __index
和 __newindex
元方法来避免这种情况。当您从用户数据请求子值时调用 __index
,当您分配用户数据的子值时调用 __newindex
。所以不需要装箱,你可以给它所有你想要的语义。
问题是在这种情况下,__index
和 __newindex
会给你难看的语法,你必须使用 m[{1,2}]
和 m[{1,2}] = 5
才能得到它以这种方式工作。
选项
因此,选项 (1) 是,为您拥有的任何类型实施某种装箱,并使用 __call
元方法。
选项 (2) 是,只需使用 __index
和 __newindex
并习惯编写 m[{1,2}]
.
选项 (3) 是,尝试使用不同的语法 m[1][2]
。然后你会想要创建一个新的 class 来表示矩阵的一行,并通过 m[1]
将其暴露给 lua。然而,这也增加了一些复杂性,您出于各种原因不想这样做。 (你在评论中表示你真的不想这样做。)
如果他们扩展 lua 语言,那么 m[1,2]
只是 m[{1,2}]
或类似语言的语法糖,那将是最好的事情。但是,我不会屏住呼吸。
如果是我,选项(3)是不可能的,我想我会选择选项(2)并习惯它。想看看是否有人知道对其进行改进。
我有一个C++矩阵class,构造函数如下:
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();
}
//
}
我实现了如下设置和获取方法:
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];}
矩阵 class 可从 Lua 访问;但是,我可以从 Lua 访问矩阵元素的唯一方法是,如果 m 是矩阵,m:GetValue 或 m:SetValue。
我想知道是否可以通过符号 m[1,2] 或 m(1,2) 访问(设置)矩阵元素,其中 m 是矩阵,[1,2] 是第一行第二列的元素。
有两个基本问题。 lua 语法和 lua 语义。
语法
就语法而言,如果您使用用户数据的 __call
元方法,m(1,2)
绝对是可能的。
我认为 m[1,2]
不可能,我认为那不可能 lua。如果您使用 __index
元方法,则可以使用 m[{1,2}]
。
语义
基本问题是 lua,如 javascript、java 和其他非 C++ 语言,使原始整数成为值类型而不是引用类型。
所以你可以很容易地让m(1,2)
return成为正确的整数,但是如果你想写m(1,2) = 5
,那就更难了,因为m(1,2)
只有return是副本,不是参考。
在 Java 中,(饱受诟病的)解决方案是使用装箱,将原始类型包装在 class 中,以便为其提供正确的(参考)语义。这里的类比是你没有 return 一个 int,你 return 一个用户数据,它在你的矩阵中包装了一个对 int 的引用。
在 lua 中,您通常使用 __index
和 __newindex
元方法来避免这种情况。当您从用户数据请求子值时调用 __index
,当您分配用户数据的子值时调用 __newindex
。所以不需要装箱,你可以给它所有你想要的语义。
问题是在这种情况下,__index
和 __newindex
会给你难看的语法,你必须使用 m[{1,2}]
和 m[{1,2}] = 5
才能得到它以这种方式工作。
选项
因此,选项 (1) 是,为您拥有的任何类型实施某种装箱,并使用 __call
元方法。
选项 (2) 是,只需使用 __index
和 __newindex
并习惯编写 m[{1,2}]
.
选项 (3) 是,尝试使用不同的语法 m[1][2]
。然后你会想要创建一个新的 class 来表示矩阵的一行,并通过 m[1]
将其暴露给 lua。然而,这也增加了一些复杂性,您出于各种原因不想这样做。 (你在评论中表示你真的不想这样做。)
如果他们扩展 lua 语言,那么 m[1,2]
只是 m[{1,2}]
或类似语言的语法糖,那将是最好的事情。但是,我不会屏住呼吸。
如果是我,选项(3)是不可能的,我想我会选择选项(2)并习惯它。想看看是否有人知道对其进行改进。