移植cinvoke-take到Lua 5.2

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了移植cinvoke-take到Lua 5.2相关的知识,希望对你有一定的参考价值。

我想在项目中使用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,但在我的情况下,我没有直接在上面的字符串推送。

答案

更换

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

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

如果你深入了解代码正在做什么,这可能会简化。

以上是关于移植cinvoke-take到Lua 5.2的主要内容,如果未能解决你的问题,请参考以下文章

S3C2440 移植最新5.2linux内核

luaL_openlib 替代 Lua 5.2

Lua 5.2 - utf8降低功能 - 是否有纯粹的lua实现?

u-boot移植---代码修改---支持DM9000网卡

有哪些选项可以在 android 项目中调用 Lua 代码?

Python相当于Lua协程?