lua userdata传递值

时间:2016-02-05 01:43:21

标签: c++ lua

我相信你们中的一些人可能会遇到这个问题。我有一个用C ++编写的用户数据对象,用通常的运算符重载方式编写,例如。

CMatrix<T>& operator=(const CMatrix<T>& b);
CMatrix<T>& operator=(const T& rhs);

在C ++中,当我创建两个矩阵时,请说AB并生成A=B,然后A和B可以用作两个独立的对象。但是,在Lua中,当我写A=B并更改B的任何属性时,A也会发生变化。

很明显,并且从Lua手册中可以看出,Lua通过引用来分配userdata,这解释了上述行为。但是,如何使A=B按值传递,以便在B更改时A不受影响。

事实上,我希望通过引用传递赋值A=B,这确实非常快,而且Matlab也是如此,但是当我第一次设置B的属性时,我希望B能够独立创建,这是我在Matlab中实现的,因为我可以从Matlab的内存使用中进行跟踪。

如果可以的话,是在C ++内部还是在lua包装器代码中的某个地方完成的?任何示例代码都会很棒。

编辑1:这是我的想法,我不确定它是否会起作用或者是否足够快

typedef struct luaelement
{
   int type;
   std::string name;
   void* addr; //newly added field
   bool isRef;  //newly added
} luaelement;

glbLuaElementSet=new set<luaelement,comparenocaseforluaelement>();

int l_newindex(lua_State* L)
{
    luaelement element;
    const char* key=lua_tostring(L,-2);
    string str=key;
    element.name=key;
    element.type=lua_type(L,-1);
    //How can I get the address, maybe a metamethod named address
    glbLuaElementSet->insert(element); 
    lua_rawset(L,1);
}

void l_registermetamethod(lua_State* L)
{
    lua_getglobal(L,"_G");
    lua_createtable(L, 0, 1);
    lua_pushcfunction(L, l_newindex);
    lua_setfield(L, -2, "__newindex");
    lua_setmetatable(L, -2);
}

现在使用glbLuaElementSet变量和l_newindex元方法,我可以跟踪在全局_G表中插入的所有变量。我打算通过检查void*地址来实现并查看是否有对已存在的userdata变量的任何引用。我不确定这是否真的有用,是否值得在性能方面付出努力。

1 个答案:

答案 0 :(得分:4)

  

但是,如何使A = B传递值,以便在B变化A时不受影响。

你不能。

请记住:Lua是动态输入。因此,虽然现在AB恰好存储了您的矩阵类型,但以后转A = 1完全没问题。现在,A存储一个整数。

C ++和Lua是非常不同的语言。在C ++中,变量是对象或对象的引用(指针是指针类型的对象)。每个变量只会保存它开始的对象。存储在该对象中的值可以更改,但对象本身存在并且具有由相关变量的生命周期定义的生命周期。

在Lua中,变量只是一个可以存储对象的框。该框与当前碰巧存储的对象没有关系;任何盒子都可以容纳任何物体。在任何时候,您都可以将该框中的内容与任何其他框中的对象进行交换。

你不能干涉将一个变量复制到另一个变量(一般来说。你可以做多元化的体操,但这只适用于那个表的成员。局部变量永远不会受到影响)。这就是Lua作为一种语言的工作原理。 C ++变量是对象; Lua变量是存储盒。最好接受你不能在Lua中编写C ++风格的代码,而是专注于在Lua中编写Lua风格的代码。

因此,如果要创建对象的副本,则必须创建该对象的副本显式

  

这是我的想法,我不确定它是否会起作用或足够快

由于几个原因,它不起作用。

首先,您将metatable应用于全局表本身,这通常是......粗鲁。

其次,即使您的代码有效,它也不适用于这样简单的事情:

globalVar = {}  --Perfectly legal to set a table inside the global table.
globalVar.value = A
globalVar.value = B  --Will not alert your copying code.

__newindex元方法不是递归。它不能在表的层次结构中上下移动。因此,存储在全局表中的表仍然可以更改其成员。

不要试图让Lua成为一件事。使用您拥有的语言,而不是您想要的语言。