Mar*_*rty 5 c ncurses linux-mint
我一直关注这篇关于" C语言交互式编程 "的博客文章.它背后的一般理想是它显示了Conway的生命游戏的实现ncurses,但游戏逻辑被加载为动态库.该main()回路监控.so的游戏,如果它发现一个新的版本重新加载交互.
我在LinuxMint 17中尝试过这个,但是ncurses在动态重新加载共享库时会挂起.我已经放入了一些调试fprintf并跟随GDB中的程序执行,程序似乎正确地重新加载库并像往常一样继续主循环.
这似乎ncurses是问题所在,但我不知道如何调试它.该ncurses功能refresh()在game.c:draw()开始返回-1一旦动态库加载.有人可以帮忙吗?代码可以在博客文章中链接的github repo中找到.
看起来库中的变量stdscr在ncurses调用之后就消失了dlclose().在我的RedHat机器上工作时不会发生这种情况.
ncurses 是您的依赖项libgame.so,而不是main可执行文件的依赖项。因此,如果您卸载动态库并加载更改后的版本,您也会卸载ncurses,然后再次加载它。但随后您无法重新初始化它。这就是你的程序失败的原因。
正确的解决方案是调用endwin()清理game_unloadncurses 的状态,然后重新初始化它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();
}
Run Code Online (Sandbox Code Playgroud)
另一种解决方案是强制链接器将 ncurses 链接到主可执行文件。这将防止动态链接器在卸载游戏库时卸载它。您可以通过在编译可执行文件时在变量-Wl,--no-as-needed前添加标志来做到这一点:$(LDLIBS)main
main : main.c game.h
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< -Wl,--no-as-needed $(LDLIBS)
Run Code Online (Sandbox Code Playgroud)
如果您更喜欢此解决方案,请考虑将 ncurses 初始化/清理也移至该main.c文件。这没有技术原因,只是干净的编码风格问题。