1

I want to use cinvoke-lua in a project, but my target environment only has Lua 5.2 available. Unfortunately, the library was written for 5.1 and is not directly backwards compatible.

I've already changed a few lua_objlen to lua_rawlen (which seems to be the correct replacement).

The (only?) other thing is a bunch of uses of LUA_GLOBALSINDEX, which doesn't exist anymore in 5.2. It is referenced 4 times in 3 functions:

struct CBStruct {
    CInvCallback *cb;
    CInvFunction *func;
    CInvContext *ctx;
    lua_Integer key;
    lua_State *l;
};

int _ccallback_gc(lua_State *l) {
    struct CBStruct *cb = touserdata(l, 1);

    lua_pushinteger(l, cb->key);
    lua_pushnil(l);
    lua_settable(l, LUA_GLOBALSINDEX);

    if (cb->cb) {
        cinv_callback_delete(cb->ctx, cb->cb);
        cb->cb = NULL;
    }
    if (cb->func) {
        cinv_function_delete(cb->ctx, cb->func);
        cb->func = NULL;
    }

    return 0;
}

void _ccallback_invoked(CInvFunction *f, void *parameters[],
    void *returnout, void *userdata) {
    struct CBStruct *cb = userdata;
    int usertable, pindex, index, retindex;
    int numargs, i;

    lua_pushinteger(cb->l, cb->key);
    lua_gettable(cb->l, LUA_GLOBALSINDEX);
    usertable = lua_gettop(cb->l);

    if (lua_isnil(cb->l, usertable)) {
        lua_pushstring(cb->l,
            "C callback being called for an object which has been collected");
        lua_error(cb->l);
    }
    lua_getfield(cb->l, usertable, "cbfunc");

    lua_getfield(cb->l, usertable, "params");
    pindex = lua_gettop(cb->l);
    numargs = (int)lua_rawlen(cb->l, pindex);

    for (i = 0; i < numargs; i++) {
        lua_pushinteger(cb->l, i + 1);
        lua_gettable(cb->l, pindex);
        index = lua_gettop(cb->l);

        unmarshal_retval(cb->l, index, parameters[i]);

        lua_remove(cb->l, index);
    }
    lua_remove(cb->l, pindex);

    lua_call(cb->l, numargs, 1);
    retindex = lua_gettop(cb->l);

    lua_getfield(cb->l, usertable, "return");
    index = lua_gettop(cb->l);
    if (!isvoid(cb->l, index)) {
        marshal_basic(cb->l, returnout, index, retindex);
    }
    lua_remove(cb->l, index);

    lua_pop(cb->l, 2); // return value and usertable
}

int _clibrary_new_callback(lua_State *l) {
    struct CBStruct *cbs;
    struct LibStruct *lib;
    CInvFunction *func;
    CInvCallback *cb;
    int i;
    void *ep;
    int retval;
    int numargs = lua_gettop(l);
    if (numargs < 3) {
        lua_pushstring(l, "usage: clibrary:new_callback(rettype, cbfunc, ...)");
        lua_error(l);
    }

    lua_getfield(l, 1, "ud");
    lib = touserdata(l, -1);
    lua_pop(l, 1);

    func = parsefunction(l, lib->ctx, 2, 1, lib->cc);

    lua_newtable(l);
    retval = lua_gettop(l);

    cbs = lua_newuserdata(l, sizeof(struct CBStruct));
    cbs->func = func;
    cbs->ctx = lib->ctx;
    cbs->l = l;

    cb = cinv_callback_create(lib->ctx, func, cbs, _ccallback_invoked);
    if (!cb) {
        lua_pushstring(l, cinv_context_geterrormsg(lib->ctx));
        cinv_function_delete(lib->ctx, func);
        lua_error(l);
    }
    cbs->cb = cb;
    cbs->key = time(NULL);

    while (1) {
        lua_pushinteger(l, cbs->key);
        lua_gettable(l, LUA_GLOBALSINDEX);
        if (!lua_isnil(l, -1)) {
            lua_pop(l, 1);
            cbs->key++;
            continue;
        }
        lua_pop(l, 1);
        lua_pushinteger(l, cbs->key);
        lua_pushvalue(l, retval);
        lua_settable(l, LUA_GLOBALSINDEX);
        break;
    }

    lua_newtable(l);
    lua_pushcfunction(l, _ccallback_gc);
    lua_setfield(l, -2, "__gc");
    lua_setmetatable(l, -2);
    lua_setfield(l, -2, "ud");

    ep = cinv_callback_getentrypoint(lib->ctx, cb);
    if (!ep) {
        lua_pushstring(l, cinv_context_geterrormsg(lib->ctx));
        lua_error(l);
    }
    lua_pushlightuserdata(l, ep);
    lua_setfield(l, -2, "ep");

    lua_pushvalue(l, 2);
    lua_setfield(l, -2, "return");

    lua_newtable(l);
    for (i = 4; i <= numargs; i++) {
        lua_pushinteger(l, i - 3);
        lua_pushvalue(l, i);
        if (isvoid(l, lua_gettop(l)))
            lua_pop(l, 2);
        else
            lua_settable(l, -3);
    }
    lua_setfield(l, -2, "params");

    lua_pushvalue(l, 3);
    lua_setfield(l, -2, "cbfunc");

    lua_pushvalue(l, 1);
    lua_setfield(l, -2, "lib");

    return 1;
}

I have literally no experience with Lua's internal workings, so it'd be much appreciated if someone could just tell me how to replace these. There are a bunch of posts about it here on Stack Overflow, but in those it seems to be used in a different context and the solution mostly is to use lua_setglobal, but in my cases I don't have string pushes directly above.

Starchild
  • 13
  • 2
  • Possible duplicate of https://stackoverflow.com/questions/10087226/lua-5-2-lua-globalsindex-alternative – lhf Dec 21 '17 at 22:13

1 Answers1

0

Replace

    lua_push*(KEY);
    lua_push*(VALUE);
    lua_settable(l, LUA_GLOBALSINDEX);

with

    lua_pushglobaltable(l);
    lua_push*(KEY);
    lua_push*(VALUE);
    lua_settable(l, -3);
    lua_pop(l,1);

and

    lua_push*(KEY);
    lua_gettable(l, LUA_GLOBALSINDEX);

with

    lua_pushglobaltable(l);
    lua_push*(KEY);
    lua_settable(l, -2);
    lua_pop(l,1);

This could probably be simplified if you dive into what the code is doing.

lhf
  • 70,581
  • 9
  • 108
  • 149
  • Thank you, I found this much clearer than the answer you linked as "possible duplicate". It compiles now, whether it actually works I'll only be able to test at a later point. – Starchild Dec 21 '17 at 22:48