对于学校项目,我使用Lua为游戏引擎添加一些脚本功能.引擎加载速度很慢,因此每次更改我的一个Lua脚本时都不必重新启动它,我希望能够重新加载脚本.我希望能够以安全可靠的方式做到这一点,即使其他剧本作者以不可预测的方式污染了全球状态.
在我看来,最简单的方法是简单地销毁lua_State我的C++代码,然后创建一个新代码,重新绑定我的函数并重新加载所有必需的脚本.但是,我在使其正常工作时遇到了一些麻烦.我有一个类作为Lua虚拟机的接口,它具有以下构造函数和析构函数:
LuaInterface::LuaInterface()
{
luaVM = lua_open();
luaL_openlibs(luaVM);
// Create the ortsgfx table.
lua_newtable(luaVM);
lua_setglobal(luaVM, TABLE_NAME);
}
LuaInterface::~LuaInterface()
{
// Close the Lua virtual machine
lua_close(luaVM);
}
Run Code Online (Sandbox Code Playgroud)
请注意,当对象的析构函数执行时,将调用lua_close(luaVM).我尝试使用以下代码从游戏引擎重置Lua:
lua.~LuaInterface();
lua = LuaInterface();
initLua();
Run Code Online (Sandbox Code Playgroud)
(当然,Lua是LuaInterface对象.)initLua()当我尝试初始化其中一个表时,这会导致分段错误. 但是,如果我lua_close(luaVM)在析构函数中删除调用,那么一切正常.
我究竟做错了什么?另外,还有更好的方法来重新加载我的Lua脚本吗?
小智 6
我有使用C++的经验,但不是Lua,所以这是我的猜测:
您的LuaInterface类可能没有实现赋值运算符和复制构造函数,否则您可能会将它们与默认构造函数和析构函数一起发布.见三规则:
http://en.wikipedia.org/wiki/Rule_of_three_(C++_programming)
如果是这样,那么这一行是导致错误的原因:
lua = LuaInterface();
Run Code Online (Sandbox Code Playgroud)
因为LuaInterface()在右边会构造一个临时实例,并且自动生成operator=会将其复制lua_State到lua.这条线之后,位于右侧的无名临时被破坏,并释放相同lua_State的是lua也相信自己.
我想到了三种解决方案:
LuaInterface声明一个私人拷贝构造函数和赋值运算符,从来没有执行这些不可复制.(这是相对常见的:http://www.artima.com/cppsource/bigtwo2.html)然后添加一个LuaInterface.reset()与析构函数相同的成员函数,后跟构造函数.您可以通过将共享部件移动到私有init()功能来保持代码清洁.(注意在此函数中使用C++异常,使对象处于无效状态.)LuaInterface不可复制,但不是LuaInterface lua使用变量,使用指针或boost::optional<LuaInterface> lua.这样,您可以销毁并重新创建变量,而无需手动调用析构函数.请LuaInterface使用新的共享引用类std::shared_ptr.您只需使用std::shared_ptr<LuaState> luaVM成员变量而不是原始指针,并在您调用的构造函数中:
luaVM.reset(lua_open(), lua_close);
在这种情况下,您甚至不需要析构函数,但是您应该阅读shared_ptr以及自动生成的成员现在所做的事情.
使用这三种解决方案中的任何一种,您就可以使用简单的赋值来重新创建状态:
lua = LuaInterface();
Run Code Online (Sandbox Code Playgroud)
现在我希望问题确实存在于C++上,而不是Lua方面.:)
| 归档时间: |
|
| 查看次数: |
3514 次 |
| 最近记录: |