【问题标题】:Not able to modify objects passed to lua无法修改传递给 lua 的对象
【发布时间】:2013-09-30 06:26:14
【问题描述】:

考虑以下使用LuaBridge 将对象传递给lua 脚本的示例:

class Test {
public:
    double d;
    Test(double t): d(t) {};
};
Test t1(10);

auto lua_state = luaL_newstate();
luaL_openlibs(lua_state);

luabridge::getGlobalNamespace(lua_state)
    .beginNamespace("Core")
        .beginClass<Test>("Test")
            .addConstructor<void(*)(double)>()
            .addData("d", &Test::d)
        .endClass()
        .addVariable("t1", &t1)
    .endNamespace()
;

显然传递的变量不能被lua修改:

Core.t1.d = 12
print(Core.t1.d)

上面的代码打印10

同样在 C++ 中处理脚本后,变量仍然保持其初始值。

luaL_dofile(lua_state, ".../test.lua");

std::cout << t1.d << std::endl; // 10

但是,不是对象成员的简单标量数据类型(如浮点数)可以被修改。我错过了什么吗?


编辑: 如果我将Test t1(10); 替换为Test *t1 = new Test(10); 甚至Test t(10); Test *t1 = &t; 并且仍然&amp;t1 传递给addVariable,那么显然是可以修改的。我不太了解这种行为,有人可以解释一下吗? (地址的地址?)

【问题讨论】:

    标签: c++ scripting lua luabridge


    【解决方案1】:

    LuaBridge 复制你的论点。如果你自己定义了一个复制构造函数并在那里放了一个断点,你会从

    /**
      Push T via copy construction from U.
    */
    template <class U>
    static inline void push (lua_State* const L, U const& u)
    

    这只是在 LuaBridge 中传递参数的一个约定。我猜是这样,因为数据具有 C++ 管理的生命周期,这是一个安全特性。你可以用一个新值重写你的数据,你会得到你想要的:

    Core.t1.d = 12
    t2 = Core.Test(10)
    t2.d=12
    print(Core.t1.d)
    print(t2.d)
    Core.t1 = t2
    print(Core.t1.d)
    

    输出

    10
    12
    12
    

    而您的 C++ - t1 端的 d 值为 12

    【讨论】:

    • 感谢您的回答,这意味着我根本无法对使用 LuaBridge 从 C++ 公开的对象使用修改方法?
    • 您可能应该将全局变量的修改包装到一个函数中。当然你可以这样做,但不是那样。最简单但不是最安全的方法是Test t1_(10); Test* t1=&amp;t1_;
    • 这就是我尝试过的并且有效。但是,对于修改方法,我的意思是class Test 中的increment 之类的方法。从 lua 调用该方法对对象也没有影响。
    • 你有静态数据。在对方法或修饰符的包装调用期间,对象被复制,因此通过方法或直接通过成员包装器进行修改没有区别。我一直在想,一个修改你的静态对象的静态函数。无论如何,无需使用 new 创建对象的指针版本就可以了。
    猜你喜欢
    • 2022-12-11
    • 2015-06-07
    • 2015-09-25
    • 2013-09-15
    • 1970-01-01
    • 2013-08-04
    • 1970-01-01
    • 2019-03-23
    • 1970-01-01
    相关资源
    最近更新 更多