I've been following along with this blog post on "Interactive Programming in C". The general ideal behind it is that it displays an implementation of Conway's Game of Life in ncurses
, but the game logic is loaded as a dynamic library. The main()
loop monitors the .so
for the game and reloads it interactively if it finds a newer version.
I've tried this in LinuxMint 17, but ncurses
hangs when the shared library is dynamically reloaded. I've put in some debug fprintf
s and followed the program execution in GDB, and the program seems to reload the library correctly and continue the main loop as usual.
It seems that ncurses
is the problem here, but I've no idea how to debug it. The ncurses
function refresh()
in game.c:draw()
starts returning -1 once the dynamic library is reloaded. Can anyone help? The code can be found in the github repo linked in the blog post.
It looks like the variable stdscr
in the ncurses
library just disappears after the call to dlclose()
. This doesn't happen on my RedHat machine at work.
ncurses is a dependency of your libgame.so
, not of the main
executable. So if you unload the dynamic library and load the changed version, you also unload ncurses and then load it again. But you then fail to reinitialize it. That is why your program fails.
The proper solution is to call endwin()
in game_unload
to cleanup ncurses's state and then reinitialize it in 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();
}
Another solution would be to force the linker to link ncurses against the main executable. This will prevent the dynamic linker from unloading it when you unload the game library. You can do that by adding the -Wl,--no-as-needed
flag before the $(LDLIBS)
variable when you compile the main
executable:
main : main.c game.h
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< -Wl,--no-as-needed $(LDLIBS)
If you prefer this solution, consider to also move the ncurses initialization/cleanup to the main.c
file. There is no technical reason for this, it's merely a matter of clean coding style.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With