example/
example.rs

1extern crate dynamic_reload;
2
3use dynamic_reload::{DynamicReload, Lib, PlatformName, Search, Symbol, UpdateState};
4use std::sync::Arc;
5use std::thread;
6use std::time::Duration;
7
8struct Plugins {
9    plugins: Vec<Arc<Lib>>,
10}
11
12impl Plugins {
13    fn add_plugin(&mut self, plugin: &Arc<Lib>) {
14        self.plugins.push(plugin.clone());
15    }
16
17    fn unload_plugins(&mut self, lib: &Arc<Lib>) {
18        for i in (0..self.plugins.len()).rev() {
19            if &self.plugins[i] == lib {
20                self.plugins.swap_remove(i);
21            }
22        }
23    }
24
25    fn reload_plugin(&mut self, lib: &Arc<Lib>) {
26        Self::add_plugin(self, lib);
27    }
28
29    // called when a lib needs to be reloaded.
30    fn reload_callback(&mut self, state: UpdateState, lib: Option<&Arc<Lib>>) {
31        match state {
32            UpdateState::Before => Self::unload_plugins(self, lib.unwrap()),
33            UpdateState::After => Self::reload_plugin(self, lib.unwrap()),
34            UpdateState::ReloadFailed(_) => println!("Failed to reload"),
35        }
36    }
37}
38
39fn main() {
40    let mut plugs = Plugins {
41        plugins: Vec::new(),
42    };
43
44    // Setup the reload handler. A temporary directory will be created inside the target/debug
45    // where plugins will be loaded from. That is because on some OS:es loading a shared lib
46    // will lock the file so we can't overwrite it so this works around that issue.
47    let mut reload_handler = DynamicReload::new(
48        Some(vec!["target/debug"]),
49        Some("target/debug"),
50        Search::Default,
51        Duration::from_secs(2),
52    );
53
54    // test_shared is generated in build.rs
55    match unsafe { reload_handler.add_library("test_shared", PlatformName::Yes) } {
56        Ok(lib) => plugs.add_plugin(&lib),
57        Err(e) => {
58            println!("Unable to load dynamic lib, err {:?}", e);
59            return;
60        }
61    }
62
63    // While this is running (printing a constant number) change return value in file src/test_shared.rs
64    // build the project with cargo build and notice that this code will now return the new value
65    loop {
66        unsafe {
67            reload_handler.update(&Plugins::reload_callback, &mut plugs);
68        }
69
70        if plugs.plugins.len() > 0 {
71            // In a real program you want to cache the symbol and not do it every time if your
72            // application is performance critical
73            let fun: Symbol<extern "C" fn() -> i32> =
74                unsafe { plugs.plugins[0].lib.get(b"shared_fun\0").unwrap() };
75
76            println!("Value {}", fun());
77        }
78
79        // Wait for 0.5 sec
80        thread::sleep(Duration::from_millis(500));
81    }
82}