我已经嵌入了Lua并在C中编写了一个非常简单的事件模块。问题是,当我尝试退出应用程序时,我收到了一个分段错误。 GDB说:
Program received signal SIGSEGV, Segmentation fault.
0x003a72c3 in luaF_newproto () from C:\Windows\SysWOW64\lua5.1.dll
模块:
#include <stdlib.h>
#include <lua.h>
#include <lauxlib.h>
#include "ice.h"
typedef struct Callback_t {
int ref;
struct Callback_t* next;
} Callback;
typedef struct Event_t {
char* name;
Callback* chead;
struct Event_t* next;
} Event;
static Event* ehead = NULL;
static Event* find_event(char* name) {
Event* current = ehead;
while (current) {
if (strcmp(current->name, name) == 0)
return current;
current = current->next;
}
return NULL;
}
static Event* add_event(char* name) {
Event* event = find_event(name);
if (event == NULL) {
event = (Event*)malloc(sizeof(Event));
if (event == NULL)
return NULL;
event->name = name;
event->chead = NULL;
event->next = ehead;
ehead = event;
}
return event;
}
static Callback* find_callback(Event* event, int ref) {
Callback* current = event->chead;
while (current) {
if (current->ref == ref)
return current;
current = current->next;
}
return NULL;
}
static Callback* add_callback(Event* event, int ref) {
Callback* callback = find_callback(event, ref);
if (callback == NULL) {
callback = (Callback*)malloc(sizeof(Callback));
if (callback == NULL)
return NULL;
callback->ref = ref;
callback->next = event->chead;
event->chead = callback;
}
return callback;
}
static int _events_subscribe(lua_State* L) {
const char* name = luaL_checkstring(L, 1);
if (!lua_isfunction(L, 2))
luaL_typerror(L, 2, lua_typename(L, LUA_TFUNCTION));
Event* event = add_event((char*)name);
if (event == NULL)
luaL_error(L, "Failed to allocate memory for event.");
Callback* callback = add_callback(event, luaL_ref(L, 2));
if (callback == NULL)
luaL_error(L, "Failed to allocate memory for event callback.");
return 0;
}
static int _events_unsubscribe(lua_State* L) {
// Not implemented yet
return 0;
}
static const luaL_reg _events_methods[] = {
{ "subscribe", _events_subscribe },
{ "unsubscribe", _events_unsubscribe },
{ NULL, NULL }
};
int luaopen_events(lua_State* L) {
luaL_openlib(L, "events", _events_methods, 0);
lua_pop(L, 1);
return 0;
}
void lua_closeevents(lua_State* L) {
Event* event = ehead;
while (event) {
Callback* callback = event->chead;
while (callback) {
Callback* cnext = callback->next;
free(callback);
callback = cnext;
}
Event* enext = event->next;
free(event);
event = enext;
}
}
主:
#include <stdlib.h>
#include <windows.h>
#include <SDL/SDL.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#include "ice.h"
lua_State* Lua;
SDL_Surface* screen;
void cleanup() {
SDL_Quit();
lua_closeevents(Lua);
lua_close(Lua);
}
int main(int argc, char** argv) {
Lua = lua_open();
if (Lua == NULL)
FATAL_ERROR("Failed to initialize Lua scripting engine.", NULL);
luaL_openlibs(Lua);
luaopen_events(Lua);
if (SDL_Init(SDL_INIT_VIDEO) == -1)
FATAL_ERROR("Failed to initialize SDL subsystems.", NULL);
atexit(cleanup);
screen = SDL_SetVideoMode(800, 600, 32, SDL_SWSURFACE);
if (screen == NULL)
FATAL_ERROR("Failed to set video mode.", NULL);
if (argc > 1) {
if (luaL_loadfile(Lua, argv[1]) != 0 || lua_pcall(Lua, 0, LUA_MULTRET, 0) != 0) {
const char* msg = lua_tostring(Lua, -1);
if (msg == NULL) msg = "No error message available.";
FATAL_ERROR("%s", msg);
}
} else {
FATAL_ERROR("No startup script specified.", NULL);
}
SDL_Event event;
do {
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_VIDEORESIZE:
DEBUG_WRITE("Resize", NULL);
screen = SDL_SetVideoMode(event.resize.w, event.resize.h,
screen->format->BitsPerPixel, screen->flags);
break;
case SDL_USEREVENT:
switch (event.user.code) {
case SDL_USER_VIDEOFLAGS:
screen = SDL_SetVideoMode(screen->w, screen->h,
screen->format->BitsPerPixel,
*(int*)event.user.data1);
break;
}
break;
default:
break;
}
}
} while (event.type != SDL_QUIT);
return EXIT_SUCCESS;
}
测试脚本:
function OnKeyDown()
return
end
events.subscribe("OnKeyDown", OnKeyDown)
如果我执行以下任一操作,我就不会遇到seg错误:
luaL_openlibs
main
的号召
add_callback
_events_subscribe
的号召
醇>
不幸的是,除了那之外,我还没有弄明白。此外,如果我在event.subscribe
之后立即调用另一个函数,则应用程序将挂起并且GDB报告:
Program received signal SIGSEGV, Segmentation fault.
0x002c00a8 in luaS_newlstr () from C:\Windows\SysWOW64\lua5.1.dll
有什么想法吗?
答案 0 :(得分:1)
我知道这会有些愚蠢。我在luaL_ref
中错误地使用了_events_subscribe
。它应该是:
Callback* callback = add_callback(event, luaL_ref(L, LUA_REGISTRYINDEX));