将cinvoke-lua移植到Lua 5.2

时间:2017-12-21 21:10:02

标签: lua

我想在项目中使用cinvoke-lua,但我的目标环境只有Lua 5.2可用。不幸的是,该库是为5.1编写的,并不直接向后兼容。

我已经将一些lua_objlen更改为lua_rawlen(这似乎是正确的替代品)。

(唯一?)其他的东西是LUA_GLOBALSINDEX的一堆用法,它在5.2中不再存在。在3个函数中引用了4次:

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;
}

我对Lua的内部工作没有任何经验,所以如果有人能告诉我如何更换这些内容,我们将非常感激。 Stack Overflow上有很多关于它的帖子,但是在那些它似乎在不同的上下文中使用,解决方案主要是使用lua_setglobal,但在我的情况下,我不会直接在上面进行字符串推送。

1 个答案:

答案 0 :(得分:0)

替换

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

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

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

data.frame(lat = c(38.6938, 38.4262, 32.7607, 37.083, 39.4619, 41.0042),
                 lon = c(-9.20587, -8.90007, -16.9595, -8.90918, -8.38391, -7.9699),
                 views = c(13565, 27020, 74420, 18550, 73253, 14615),
                 challenge = c("SPOT CIDADE", "SPOT NATUREZA I",
                               "SPOT NATUREZA II", "SPOT ROMANCE",
                               "SPOT PATRIMONIO", "SPOT GASTRONOMIA"),
                 stringsAsFactors = FALSE)

如果你深入了解代码的作用,这可能会被简化。