summaryrefslogtreecommitdiff
path: root/src/util_linux.h
blob: 4040a102e98da32aff01b186a37e54749af65d66 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#ifndef UTIL_LINUX_H
#define UTIL_LINUX_H

#include <dlfcn.h>
#include <sys/stat.h>


time_t file_get_modified_time(char *file_path)
{
    time_t mtime = 0;
    struct stat file_status = {0};
    if (stat(file_path, &file_status) == 0)
    {
        //printf("File: %s last modified: %s\n", file_path, ctime(&file_status.st_mtime));
        mtime = file_status.st_mtime;
    }
    else
    {
        fprintf(stderr, "ERROR: Failed to stat file: %s\n", file_path);
    }
    return mtime;
}


void unload_game_code(struct SDLGameCode *game_code)
{
    if (!game_code)
    {
        printf("Invalid pointer *game_code\n");
        return;
    }

    if (game_code->game_code_library)
    {
        dlclose(game_code->game_code_library);
        game_code->game_code_library = 0;
    }
    game_code->is_valid = false;
    game_code->game_update = 0;
    game_code->game_render = 0;
}


// TODO: Add backup dll in case loading fails
struct SDLGameCode load_game_code(char *source_lib_path)
{
    struct SDLGameCode game_code = {0};

    game_code.last_write_time = file_get_modified_time(source_lib_path);
    if (game_code.last_write_time)
    {
        game_code.game_code_library = dlopen(source_lib_path, RTLD_LAZY);
        if (game_code.game_code_library)
        {
            // NOTE: The C standard (as of C99) distinguishes function pointers
            // from object pointers (`void *` is an object pointer). Technically it
            // is undefined behavior to cast between these two pointer types. In
            // practice, it works on most modern platforms.
            //
            // In this case, we are protected by POSIX, which specifies that
            // function and data pointers must be the same size. We will only ever
            // be using dlsym on POSIX-compliant platforms.
            game_code.game_update = (game_update_t *) dlsym(game_code.game_code_library, "game_update");
            game_code.game_render = (game_render_t *) dlsym(game_code.game_code_library, "game_render");
            game_code.is_valid = (game_code.game_update && game_code.game_render);
        }
    }

    if (!game_code.is_valid)
    {
        fprintf(stderr, "ERROR: Game code is not valid: %s\n", dlerror());
    }

    return game_code;
}


#endif