luaL_dofile在已知良好的字节码上失败,可以使用未编译的版本



我已经组装了一个非常简单的Lua引擎,但它似乎拒绝了在Lua控制台中工作的字节码。未编译的版本在引擎中工作。我是不是用错了luac?

我使用给定的命令进行编译,并以"的形式运行/a.out'.

res/default.loa:

print("Setting up world structure.")

luac命令:

luac -o res/default.lux res/default.lua

MWE:

#define SCRIPTDIR "res/"
#define THROW_IF_NONZERO(x,m) if((x)!=0) throw std::runtime_error(m);
#define THROW_IF_ZERO(x,m) if((x)==0) throw std::runtime_error(m);
extern "C" {
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
}
#include "sys/stat.h"
#include <string>
#include <system_error>
#include <iostream>
using std::string;
class Entity {
private:
lua_State *m_lua;
public:
Entity() : Entity(nullptr) { }
Entity(lua_State *lua) : m_lua{lua} { }
virtual ~Entity() { }
void load_and_run(string);
};
class WorldEntity : public Entity {
public:
WorldEntity(lua_State *lua) : Entity(lua) {
luaL_openlibs(lua);
}
~WorldEntity() { }
};
int main() {
lua_State *lua{nullptr};
try {
lua = luaL_newstate();
WorldEntity eWorld{lua};
eWorld.load_and_run("default"); // load default.lua/lux
} catch(std::exception &e) {
if (lua != nullptr) {
lua_close(lua);
}
std::cout << "Error: " << e.what() << std::endl;
}
return 0;
}
void Entity::load_and_run(string filename) {
THROW_IF_ZERO(m_lua, "Lua not started.");
filename = SCRIPTDIR + filename + ".lux";
struct stat sb;
int rc = stat(filename.c_str(), &sb);
if (rc == -1) {
filename.pop_back();
filename += "a";
rc = stat(filename.c_str(), &sb);
THROW_IF_NONZERO(rc, "File not found!");
}
std::cout << "File: " << filename << std::endl;
// Currently won't run compiled Lua scripts, not sure why.
rc = luaL_dofile(m_lua, filename.c_str());
THROW_IF_NONZERO(rc, "Could not load lua file.");
}

编译命令:

gcc src/bug001mwe.cpp -std=c++14 -llua -lstdc++

脚本的正确输出:

File: res/default.lua
Setting up world structure.

字节码输出错误:

File: res/default.lux
Error: Could not load lua file.

两个文件,从lua控制台输出:

Setting up world structure.

让我困惑的是,它在lua控制台中工作,但在我的程序中不工作。在调用luaL_dofile之后,我添加了一个对lua_tostring的调用,如下所示:

rc = luaL_dofile(m_lua, filename.c_str());
std::ostringstream ostr;
ostr << "Could not load lua file. ";
ostr << lua_tostring(m_lua, -1);
THROW_IF_NONZERO(rc, ostr.str());

错误字符串变为:

Error: Could not load lua file. res/default.lux: version mismatch in precompiled chunk

怎么了?

长话短说,由于一些不相关的东西中的包依赖关系过时,我安装了以前版本的Lua。旧的luac拦截了luac命令,并编译为有效但不兼容的字节码。卸载了我并不真正需要的无关软件包,现在一切都正常了。

这个故事的寓意是:总是检查Lua堆栈上的错误字符串,它(可能(会告诉你出了什么问题。

最新更新