#define _DEFAULT_SOURCE // usleep() #include #include #include #include #include #include // #include "inotify-syscalls.h" #include "include/raylib.h" #include "include/raymath.h" #include "boids_game.h" #define SCREEN_WIDTH 1300 #define SCREEN_HEIGHT 1080 #define TARGET_FPS 60 const char *GAME_LIB = "./libboids.so"; char epoll_buf[1024]; struct Game { void *handle; struct GameApi api; struct GameState *state; }; #define MAX_EVENTS 1 void load_game(struct Game *game) { void *handle = dlopen(GAME_LIB, RTLD_NOW); if (handle) { game->handle = handle; const struct GameApi *api = dlsym(game->handle, "GAME_API"); if (api != NULL) { printf("Loaded API, calling init()\n"); game->api = *api; game->state = game->api.init(); } else { printf("Failed to load API\n"); dlclose(game->handle); } } else { fprintf(stderr, "Error loading %s\n", GAME_LIB); fprintf(stderr, "Error was: %s\n", dlerror()); exit(1); } } int main(void) { int fd = inotify_init(); if (fd < 0) { fprintf(stderr, "Error initializing inotify\n"); } int wd; wd = inotify_add_watch(fd, GAME_LIB, IN_MODIFY); // create epoll instance int epollfd = epoll_create1(0); if (epollfd == -1) { fprintf(stderr, "Error creating epoll instance\n"); } struct epoll_event event; event.events = EPOLLIN; event.data.fd = fd; if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event) == -1) { fprintf(stderr, "Error adding inotify descriptor to epoll\n"); } struct epoll_event events[MAX_EVENTS]; struct Game game = {0}; load_game(&game); while (!WindowShouldClose()) { int nfds = epoll_wait(epollfd, events, MAX_EVENTS, 0); if (nfds == -1) { fprintf(stderr, "epoll_wait failed\n"); break; } for (int n = 0; n < nfds; ++n) { if (events[n].data.fd == fd) { printf("SO has been updated!\n"); // This clears the inotify queue so we don't get any more events read(fd, epoll_buf, sizeof(epoll_buf)); } } game.api.step(game.state); } inotify_rm_watch(fd, wd); close(fd); close(epollfd); CloseWindow(); }