C タイマー (アラームではない) をラップし、それを lua 内で使用して、1 秒が経過した後にトリガーされるコールバック関数を指定できるようにしたいと考えています。複数のタイマーを使用するため、タイマーIDとコールバックをテーブルに格納するのですが、「lua_rawset」呼び出し時にセグメンテーションフォルトが発生したため、stack_dumpを使用してluaスタックをチェックすると、「lua_rawget」でnilが返されました。 66(lr_register_timer、FIXME でマーク)、ここで何が問題なのですか? すみません、私の英語は下手です。乾杯。
ルアコード:
local lt = luatimer
lt.register_timer(1, function(id)
io.stdout:write("id" .. id .. "timeout\n");
end)
C コード:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include "timer.h"
static lua_State *L;
static void stack_dump(lua_State *L, FILE *fp)
{
int i;
int top = lua_gettop(L);
for (i = 1; i <= top; i++) {
int t = lua_type(L, i);
switch (t) {
case LUA_TSTRING: fprintf(fp, "'%s'", lua_tostring(L, i)); break;
case LUA_TBOOLEAN: fprintf(fp, lua_toboolean(L, i) ? "true" : "false"); break;
case LUA_TNUMBER: fprintf(fp, "%g", lua_tonumber(L, i)); break;
default: fprintf(fp, "%s", lua_typename(L, t)); break;
}
fprintf(fp, " ");
}
fprintf(fp, "\n");
}
struct timer_env {
int id;
struct event *ev;
};
static void callback_timer_wrap(int id, void *arg)
{
struct timer_env *env = arg;
/* get timer id table */
lua_pushlightuserdata(L, &L);
lua_rawget(L, LUA_REGISTRYINDEX);
lua_pushinteger(L, env->id);
lua_gettable(L, -2);
/* call lua handler with one result */
lua_pushinteger(L, env->id);
if (lua_pcall(L, 1, 1, 0) == 0) {
lua_pop(L, 1); /* pop result */
}
}
/* id, callback */
static int lr_register_timer(lua_State *L)
{
struct timer_env *env;
int id;
int err;
id = (int)luaL_checkinteger(L, 1);
if (!lua_isfunction(L, 2) || lua_iscfunction(L, 2))
return 0;
/* set lua handler */
lua_pushlightuserdata(L, &L);
lua_rawget(L, LUA_REGISTRYINDEX); /* FIXME */
lua_pushvalue(L, 1); /* key: id */
lua_pushvalue(L, 2); /* value: callback */
stack_dump(L, stderr);
/* FIXME crashed */
lua_rawset(L, -3);
lua_pop(L, 1);
env = malloc(sizeof(*env));
memset(env, 0, sizeof(*env));
env->id = id;
if ((err = register_timer(id, callback_timer_wrap, env)) < 0)
free(env);
lua_pushinteger(L, err);
return 1;
}
static const luaL_Reg luatimer_lib[] = {
{ "register_timer", lr_register_timer },
{ NULL, NULL }
};
static int luaopen_luatimer(lua_State *L)
{
luaL_register(L, "luatimer", luatimer_lib);
/* timer id table */
lua_pushlightuserdata(L, &L); /* key */
lua_newtable(L); /* value */
lua_rawset(L, LUA_REGISTRYINDEX);
return 1;
}
int luaenv_init(void)
{
L = luaL_newstate();
luaL_openlibs(L);
lua_pushcfunction(L, luaopen_luatimer);
lua_pushstring(L, "luatimer");
lua_call(L, 1, 0);
return 0;
}
void luaenv_exit(void)
{
if (L)
lua_close(L);
}