{"id":13503178,"url":"https://github.com/emoon/dynamic_reload","last_synced_at":"2025-05-16T12:05:46.807Z","repository":{"id":3900661,"uuid":"51264280","full_name":"emoon/dynamic_reload","owner":"emoon","description":"Dynamic reloading of shared libraries","archived":false,"fork":false,"pushed_at":"2023-08-15T17:58:45.000Z","size":101,"stargazers_count":383,"open_issues_count":4,"forks_count":26,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-05-11T05:04:50.525Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/emoon.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2016-02-07T20:16:21.000Z","updated_at":"2025-03-25T17:39:39.000Z","dependencies_parsed_at":"2024-01-14T06:51:44.060Z","dependency_job_id":"63fc32b0-9ec0-4b90-92bd-dd779c00654f","html_url":"https://github.com/emoon/dynamic_reload","commit_stats":{"total_commits":125,"total_committers":12,"mean_commits":"10.416666666666666","dds":"0.23199999999999998","last_synced_commit":"9ea60df1a1e99357f49c8a461268baac1bbd181a"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emoon%2Fdynamic_reload","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emoon%2Fdynamic_reload/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emoon%2Fdynamic_reload/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emoon%2Fdynamic_reload/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/emoon","download_url":"https://codeload.github.com/emoon/dynamic_reload/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254527085,"owners_count":22085918,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T22:02:40.177Z","updated_at":"2025-05-16T12:05:46.756Z","avatar_url":"https://github.com/emoon.png","language":"Rust","funding_links":[],"categories":["Rust"],"sub_categories":[],"readme":"[![Build Status](https://github.com/emoon/dynamic_reload/workflows/Rust/badge.svg)](https://github.com/emoon/dynamic_reload/actions?workflow=Rust)\n[![Coverage Status](https://coveralls.io/repos/github/emoon/dynamic_reload/badge.svg?branch=master)](https://coveralls.io/github/emoon/dynamic_reload?branch=master) \n[![Crates.io](https://img.shields.io/crates/v/dynamic_reload.svg)](https://crates.io/crates/dynamic_reload) \n[![Documentation](https://docs.rs/dynamic_reload/badge.svg)](https://docs.rs/dynamic_reload)\n\ndynamic_reload is a cross platform library written in [Rust](https://www.rust-lang.org) that makes it easier to do reloading of shared libraries (dll:s on windows, .so on *nix, .dylib on Mac, etc). The intended use is to allow applications to reload code on the fly without closing down the application when some code changes. This can be seen as a lite version of \"live\" coding for Rust. It's worth to mention here that reloading of shared libraries isn't limited to libraries written in Rust but can be done in any language that can target shared libraries. A typical scenario can look like this:\n\n```\n1. Application Foo starts.\n2. Foo loads the shared library Bar.\n3. The programmer needs to make some code changes to Bar.\n   Instead of closing down Foo the programmer does the change, recompiles the code.\n4. Foo will detect that Bar has been changed on the disk,\n   will unload the old version and load the new one.\n```\n\ndynamic_reload library will not try to solve any stale data hanging around in Foo from Bar. It is up to Foo to make sure all data has been cleaned up before Foo is reloaded. Foo will be getting a callback from dynamic_reload before Bar is reloaded and that allows Foo to take needed action. Then another call will be made after Bar has been reloaded to allow Foo to restore state for Bar if needed.\n\nUsage\n-----\n\n```toml\n# Cargo.toml\n[dependencies]\ndynamic_reload = \"0.10.0\"\n\n```\n\nExample\n-------\n\nTo actually test reloading of this example do the following\n\n```\n1, cargo run --example example\n2. In another shell change src/test_shared.rs to return another value\n3. Run cargo build\n4. Notice that the value return in 1. is now changed\n```\n\n```rust\nuse dynamic_reload::{DynamicReload, Lib, Symbol, Search, PlatformName, UpdateState};\nuse std::{sync::Arc, time::Duration, thread};\n\nstruct Plugins {\n    plugins: Vec\u003cArc\u003cLib\u003e\u003e,\n}\n\nimpl Plugins {\n    fn add_plugin(\u0026mut self, plugin: \u0026Arc\u003cLib\u003e) {\n        self.plugins.push(plugin.clone());\n    }\n\n    fn unload_plugins(\u0026mut self, lib: \u0026Arc\u003cLib\u003e) {\n        for i in (0..self.plugins.len()).rev() {\n            if \u0026self.plugins[i] == lib {\n                self.plugins.swap_remove(i);\n            }\n        }\n    }\n\n    fn reload_plugin(\u0026mut self, lib: \u0026Arc\u003cLib\u003e) {\n        Self::add_plugin(self, lib);\n    }\n\n    // called when a lib needs to be reloaded.\n    fn reload_callback(\u0026mut self, state: UpdateState, lib: Option\u003c\u0026Arc\u003cLib\u003e\u003e) {\n        match state {\n            UpdateState::Before =\u003e Self::unload_plugins(self, lib.unwrap()),\n            UpdateState::After =\u003e Self::reload_plugin(self, lib.unwrap()),\n            UpdateState::ReloadFailed(_) =\u003e println!(\"Failed to reload\"),\n        }\n    }\n}\n\nfn main() {\n    let mut plugs = Plugins { plugins: Vec::new() };\n\n    // Setup the reload handler. A temporary directory will be created inside the target/debug\n    // where plugins will be loaded from. That is because on some OS:es loading a shared lib\n    // will lock the file so we can't overwrite it so this works around that issue.\n    let mut reload_handler = DynamicReload::new(Some(vec![\"target/debug\"]),\n                                                Some(\"target/debug\"),\n                                                Search::Default,\n                                                Duration::from_sec(2));\n\n    // test_shared is generated in build.rs\n    match reload_handler.add_library(\"test_shared\", PlatformName::Yes) {\n        Ok(lib) =\u003e plugs.add_plugin(\u0026lib),\n        Err(e) =\u003e {\n            println!(\"Unable to load dynamic lib, err {:?}\", e);\n            return;\n        }\n    }\n\n    //\n    // While this is running (printing a number) change return value in file src/test_shared.rs\n    // build the project with cargo build and notice that this code will now return the new value\n    //\n    loop {\n        reload_handler.update(Plugins::reload_callback, \u0026mut plugs);\n\n        if plugs.plugins.len() \u003e 0 {\n            // In a real program you want to cache the symbol and not do it every time if your\n            // application is performance critical\n            let fun: Symbol\u003cextern \"C\" fn() -\u003e i32\u003e = unsafe {\n                plugs.plugins[0].lib.get(b\"shared_fun\\0\").unwrap()\n            };\n\n            println!(\"Value {}\", fun());\n        }\n\n        // Wait for 0.5 sec\n        thread::sleep(Duration::from_millis(500));\n    }\n}\n```\n\n## Acknowledgment\n\ndynamic_reload uses these two crates for most of the heavy lifting. Thanks!\n\nNotify: https://github.com/passcod/rsnotify\n\nlibloading: https://github.com/nagisa/rust_libloading/\n\n## License\n\nLicensed under either of\n\n * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)\n * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)\n\nat your option.\n\n### Contribution\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femoon%2Fdynamic_reload","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Femoon%2Fdynamic_reload","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femoon%2Fdynamic_reload/lists"}