Port lua (5.2-5.4) C++ connection to lua 5.1?

97 Views Asked by At

I'm working on the mGBA project (https://github.com/mgba-emu/mgba) and I'm trying to fix some problems regarding the scripting API and Lua 5.1.

The project has the following functions:

Load the Lua script:

bool _luaLoad(struct mScriptEngineContext* ctx, const char* filename, struct VFile* vf) {
    struct mScriptEngineContextLua* luaContext = (struct mScriptEngineContextLua*) ctx;
    struct mScriptEngineLuaReader data = {
        .vf = vf
    };
    if (luaContext->lastError) {
        free(luaContext->lastError);
        luaContext->lastError = NULL;
    }
    char name[PATH_MAX + 1];
    char dirname[PATH_MAX];
    name[0] = '\0';
    dirname[0] = '\0';
    if (filename) {
        if (*filename == '*') {
            snprintf(name, sizeof(name), "=%s", filename + 1);
        } else {
            const char* lastSlash = strrchr(filename, '/');
            const char* lastBackslash = strrchr(filename, '\\');
            if (lastSlash && lastBackslash) {
                if (lastSlash < lastBackslash) {
                    lastSlash = lastBackslash;
                }
            } else if (lastBackslash) {
                lastSlash = lastBackslash;
            }
            if (lastSlash) {
                size_t len = lastSlash - filename + 1;
                if (sizeof(dirname) < len) {
                    len = sizeof(dirname);
                }
                strlcpy(dirname, filename, len);
            }
            snprintf(name, sizeof(name), "@%s", filename);
        }
        filename = name;
    }
#if LUA_VERSION_NUM >= 502
    int ret = lua_load(luaContext->lua, _reader, &data, filename, "t");
#else
    int ret = lua_load(luaContext->lua, _reader, &data, filename);
#endif
    switch (ret) {
    case LUA_OK:
        // Create new _ENV
        lua_newtable(luaContext->lua);

        // Make the old _ENV the __index in the metatable
        lua_newtable(luaContext->lua);
        lua_pushliteral(luaContext->lua, "__index");
#if LUA_VERSION_NUM >= 502
        lua_getupvalue(luaContext->lua, -4, 1);
#else
        lua_getfenv(luaContext->lua, -4);
#endif
        lua_rawset(luaContext->lua, -3);

        lua_pushliteral(luaContext->lua, "__newindex");
#if LUA_VERSION_NUM >= 502
        lua_getupvalue(luaContext->lua, -4, 1);
#else
        lua_getfenv(luaContext->lua, -4);
#endif
        lua_rawset(luaContext->lua, -3);

        lua_setmetatable(luaContext->lua, -2);

        lua_pushliteral(luaContext->lua, "script");
        lua_newtable(luaContext->lua);

        if (dirname[0]) {
            lua_pushliteral(luaContext->lua, "require");
            lua_pushstring(luaContext->lua, dirname);
            lua_pushcclosure(luaContext->lua, _luaRequireShim, 1);
            lua_rawset(luaContext->lua, -5);

            lua_pushliteral(luaContext->lua, "dir");
            lua_pushstring(luaContext->lua, dirname);
            lua_rawset(luaContext->lua, -3);
        }

        if (name[0] == '@') {
            lua_pushliteral(luaContext->lua, "path");
            lua_pushstring(luaContext->lua, &name[1]);
            lua_rawset(luaContext->lua, -3);
        }

        lua_rawset(luaContext->lua, -3);
        lua_setupvalue(luaContext->lua, -2, 1);
        luaContext->func = luaL_ref(luaContext->lua, LUA_REGISTRYINDEX);
        return true;
    case LUA_ERRSYNTAX:
        luaContext->lastError = strdup(lua_tostring(luaContext->lua, -1));
        lua_pop(luaContext->lua, 1);
        break;
    default:
        break;
    }
    return false;
}

Run the script:

bool _luaRun(struct mScriptEngineContext* context) {
    struct mScriptEngineContextLua* luaContext = (struct mScriptEngineContextLua*) context;

    lua_rawgeti(luaContext->lua, LUA_REGISTRYINDEX, luaContext->func);
    return _luaInvoke(luaContext, NULL);
}

bool _luaInvoke(struct mScriptEngineContextLua* luaContext, struct mScriptFrame* frame) {
    int nargs = 0;
    if (frame) {
        nargs = mScriptListSize(&frame->arguments);
    }

    if (luaContext->lastError) {
        free(luaContext->lastError);
        luaContext->lastError = NULL;
    }

    if (frame && !_luaPushFrame(luaContext, &frame->arguments)) {
        return false;
    }

    lua_pushliteral(luaContext->lua, "mCtx");
    lua_pushlightuserdata(luaContext->lua, luaContext);
    lua_rawset(luaContext->lua, LUA_REGISTRYINDEX);
    int ret = lua_pcall(luaContext->lua, nargs, LUA_MULTRET, 0);
    lua_pushliteral(luaContext->lua, "mCtx");
    lua_pushnil(luaContext->lua);
    lua_rawset(luaContext->lua, LUA_REGISTRYINDEX);

    if (ret == LUA_ERRRUN) {
        luaContext->lastError = strdup(lua_tostring(luaContext->lua, -1));
        lua_pop(luaContext->lua, 1);
    }
    if (ret) {
        return false;
    }

    if (frame && !_luaPopFrame(luaContext, &frame->returnValues)) {
        mScriptContextDrainPool(luaContext->d.context);
        return false;
    }
    mScriptContextDrainPool(luaContext->d.context);

    return true;
}

This works flawlessly with Lua 5.2-5.4, but with Lua 5.1 it gives the following error with every script I've tried, even with a script with only the line print("Hello world"):

"attempt to call a table value"

I think this is related to the environments (in fact, thanks to the first comment here I fixed that) but I'm not sure.

Is there any thing I'm missing here?

Thanks!

0

There are 0 best solutions below