我一直关注" Interactive Programming in C"上的这篇博客文章。它背后的一般理想是它在ncurses
中显示了Conway的生命游戏的实现,但游戏逻辑被加载为动态库。 main()
循环监视游戏的.so
,如果找到更新版本,则以交互方式重新加载。
我已在LinuxMint 17中尝试过此操作,但ncurses
在动态重新加载共享库时挂起。我已经输入了一些调试fprintf
并跟随GDB中的程序执行,程序似乎正确地重新加载库并像往常一样继续主循环。
ncurses
似乎是问题,但我不知道如何调试它。重新加载动态库后,ncurses
中的refresh()
函数game.c:draw()
开始返回-1。有人可以帮忙吗?该代码可以在博文中链接的github repo中找到。
看起来stdscr
库中的变量ncurses
在调用dlclose()
后就消失了。这在我工作的RedHat机器上不会发生。
答案 0 :(得分:3)
ncurses是libgame.so
的依赖关系,而不是main
可执行文件的依赖关系。因此,如果卸载动态库并加载更改后的版本,还可以卸载ncurses,然后再次加载它。但是你没有重新初始化它。这就是你的程序失败的原因。
正确的解决方案是调用endwin()
中的game_unload
来清理ncurses状态,然后在game_reload
中重新初始化它:
static void game_reload(struct game_state *state)
{
initscr();
raw();
timeout(0);
noecho();
curs_set(0);
keypad(stdscr, TRUE);
}
static void game_unload(struct game_state *state)
{
endwin();
}
另一种解决方案是强制链接器将ncurses链接到主可执行文件。这将阻止动态链接器在卸载游戏库时卸载它。您可以通过在编译-Wl,--no-as-needed
可执行文件时在$(LDLIBS)
变量之前添加main
标志来实现此目的:
main : main.c game.h
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< -Wl,--no-as-needed $(LDLIBS)
如果您更喜欢此解决方案,请考虑将ncurses初始化/清除移至main.c
文件。这没有技术上的原因,只是清晰的编码风格。