移植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的主要内容,如果未能解决你的问题,请参考以下文章
Lua 5.2 - utf8降低功能 - 是否有纯粹的lua实现?