diff options
| author | Jeroen van Rijn <Kelimion@users.noreply.github.com> | 2024-01-19 18:43:02 +0100 |
|---|---|---|
| committer | Jeroen van Rijn <Kelimion@users.noreply.github.com> | 2024-01-19 18:43:02 +0100 |
| commit | e8102a40d03b06fbb48318577cbcbec8325ae1a9 (patch) | |
| tree | 8336fa7d501d0d6aa71e4df633dd1c92f81c206f /core/dynlib | |
| parent | 737677f1b669a188e8867a46bde088a14f01dc77 (diff) | |
Add hot reload support to `dynlib.initialize_symbols`
Diffstat (limited to 'core/dynlib')
| -rw-r--r-- | core/dynlib/example/example.odin | 11 | ||||
| -rw-r--r-- | core/dynlib/lib.odin | 12 |
2 files changed, 20 insertions, 3 deletions
diff --git a/core/dynlib/example/example.odin b/core/dynlib/example/example.odin index 78b14f5c0..f12233b0a 100644 --- a/core/dynlib/example/example.odin +++ b/core/dynlib/example/example.odin @@ -26,7 +26,16 @@ main :: proc() { // The library's Handle (to unload) will be stored in `sym._my_lib_handle`. This way you can load multiple DLLs in one struct. count, ok := dynlib.initialize_symbols(&sym, "lib.dll", "foo_", "_my_lib_handle") defer dynlib.unload_library(sym._my_lib_handle) - fmt.printf("ok: %v. %v symbols loaded from lib.dll (%p).\n", ok, count, sym._my_lib_handle) + fmt.printf("(Initial DLL Load) ok: %v. %v symbols loaded from lib.dll (%p).\n", ok, count, sym._my_lib_handle) + + if count > 0 { + fmt.println("42 + 42 =", sym.add(42, 42)) + fmt.println("84 - 13 =", sym.sub(84, 13)) + fmt.println("hellope =", sym.hellope^) + } + + count, ok = dynlib.initialize_symbols(&sym, "lib.dll", "foo_", "_my_lib_handle") + fmt.printf("(DLL Reload) ok: %v. %v symbols loaded from lib.dll (%p).\n", ok, count, sym._my_lib_handle) if count > 0 { fmt.println("42 + 42 =", sym.add(42, 42)) diff --git a/core/dynlib/lib.odin b/core/dynlib/lib.odin index 6a5c919a3..e9ee77d2c 100644 --- a/core/dynlib/lib.odin +++ b/core/dynlib/lib.odin @@ -115,17 +115,19 @@ Optionally also takes the struct member to assign the library handle to, `__hand This allows using one struct to hold library handles and symbol pointers for more than 1 dynamic library. +Loading the same library twice unloads the previous incarnation, allowing for straightforward hot reload support. + Returns: * `-1, false` if the library could not be loaded. * The number of symbols assigned on success. `ok` = true if `count` > 0 See doc.odin for an example. */ -initialize_symbols :: proc(symbol_table: ^$T, library_name: string, symbol_prefix := "", handle_field_name := "__handle") -> (count: int, ok: bool) where intrinsics.type_is_struct(T) { +initialize_symbols :: proc(symbol_table: ^$T, library_path: string, symbol_prefix := "", handle_field_name := "__handle") -> (count: int, ok: bool) where intrinsics.type_is_struct(T) { assert(symbol_table != nil) handle: Library - if handle, ok = load_library(library_name); !ok { + if handle, ok = load_library(library_path); !ok { return -1, false } @@ -143,6 +145,12 @@ initialize_symbols :: proc(symbol_table: ^$T, library_name: string, symbol_prefi // If we've come across the struct member for the handle, store it and continue scanning for other symbols. if field_name == handle_field_name { + // We appear to be hot reloading. Unload previous incarnation of the library. + if old_handle := (^Library)(field_ptr)^; old_handle != nil { + if ok = unload_library(old_handle); !ok { + return count, ok + } + } (^Library)(field_ptr)^ = handle continue } |